systemd unit is masked — the /dev/null execution
systemctl says your unit is masked and won't start. The mask is one symlink to /dev/null — three commands cure it, and systemd-delta lists every mask.
Masked means one symlink:
/etc/systemd/system/<unit>.service → /dev/null. Remove the symlink (systemctl unmask), reload (systemctl daemon-reload), start (systemctl start <unit>) — the unit boots. Inventory every mask withsystemd-delta --type=masked.
Tested on a throwaway Arch Linux VM, cloud image, systemd 262, last tested 2026-11-05. Every line below is lifted from that run, unedited.
A sibling piece from September covered units that fail to start loudly — systemd service not starting: the log already named the cause. A masked unit is the opposite crime. Here the log says nothing, because the log is part of what got masked.
Why does systemctl call my unit masked?
Because systemctl mask — or whoever laid the mask — created exactly one symlink where your unit's local path should be. That is the entire mechanism. Run it yourself and systemd admits it in plain words:
$ sudo systemctl mask systemd-timesyncd
Created symlink '/etc/systemd/system/systemd-timesyncd.service' → '/dev/null'.
When the loader is asked to start the unit, it resolves /etc/systemd/system/systemd-timesyncd.service, lands on /dev/null, finds an empty file where a unit definition should be, and refuses:
$ sudo systemctl start systemd-timesyncd
Failed to start systemd-timesyncd.service: Unit systemd-timesyncd.service is masked.
systemctl is-enabled answers masked. The unit file in /usr/lib/systemd/system is untouched, valid, and completely unreachable — the void sits in front of it.
The symlink is the mask. Not a flag in a config file, not a state in a database — a filesystem object you can hold with ls. Delete it and the machine forgets the mask ever existed.
Why is my masked unit still running?
Here is the trap that eats an afternoon: masked does not mean stopped. The mask is a check performed on the next start, enable, or link. Whatever is already alive keeps living. From the same bench run, taken after the mask:
$ systemctl status systemd-timesyncd --no-pager -n 0
● systemd-timesyncd.service
Loaded: masked (Reason: Unit systemd-timesyncd.service is masked.)
Active: active (running) since Thu 2026-11-05 05:10:21 UTC; 1min 28s ago
Main PID: 320
Status: "Contacted time server 213.219.38.86:123 (2.arch.pool.ntp.org)."
Loaded: masked and Active: active (running) on adjacent lines, both true at once. PID 320 kept serving NTP for the entire minute and a half the mask existed, and would have kept going until stop, restart, or reboot. If your masked unit is something load-bearing and you expected the mask to pause it, it did not — stop it yourself.
Why does the journal have no line for it?
Because the refusal is written to your terminal, not to the journal. The bench run's witness check — three minutes of journal around the mask, counted:
$ sudo journalctl -u systemd-timesyncd --since '-3 min' --no-pager | wc -l
9
Nine lines in the window. Every one is the running process's own chatter — time-server contacts. Zero lines mention the mask, and zero mention the refused start. The one administrative event that changed the unit's fate is invisible to the exact tool you will open first. /dev/null is systemd filing a unit under gone, and let it stay gone — and not filing a report. The two refusals do differ, usefully, in what they name:
| command | what it prints | the subject it names |
|---|---|---|
systemctl start | Failed to start … Unit systemd-timesyncd.service is masked. | the unit |
systemctl enable | Failed to enable unit: Unit /etc/systemd/system/systemd-timesyncd.service is masked | the symlink path |
Start names the unit; enable names the path. Same void, two alibis. A mask is the one execution on your machine that leaves no statement in the journal — the filesystem is the only witness.
How do I find every masked unit on the machine?
One command inventories them all — systemd-delta, which reports local overrides, including the fatal kind:
$ systemd-delta --type=masked
[MASKED] /etc/systemd/system/systemd-timesyncd.service → /usr/lib/systemd/system/systemd-timesyncd.service
1 overridden configuration files found.
verify: systemd-delta --type=masked lists every masked unit with its real target — run it on any box you inherit.
systemctl list-unit-files --state=masked reads the same truth from the unit-file cache and answers with a count. Both beat grep -r through /etc/systemd/system, and both fit in a handover note. If you administer boxes other people built, run the delta before you trust any "broken" unit — a mask left by a hardening script or a forgotten fight with an NTP daemon looks identical to a corrupt package from the outside.
How do I unmask a systemd service?
Three commands, in order:
verify: systemctl list-unit-files --state=masked → 0 unit files listed. — that is the cured machine, straight from the bench run.
Skipping daemon-reload usually works and occasionally doesn't — the reload costs a second, so spend it.
Who masked it, and when?
The honest ledger: three usual suspects. Your own past self (masked during a migration and never revisited), a package war (distros mask the NTP or DNS resolver they lose to — the exact unit in this bench run, systemd-timesyncd, is the one the search engines see people asking about), and hardening scripts that mask everything they don't understand. None of the three confess in the journal. The only statement of intent anyone gets is the symlink's own timestamp:
$ stat -c '%y %n' /etc/systemd/system/<unit>.service
Run that before you unmask on a shared box. The date tells you whether you are undoing last night's security script or a war someone won three years ago. Then unmask, reload, start — and if the unit was running the whole time, congratulate it: it served through its own funeral.