Relationships
#1414 worker daemon enable: relative/missing --cache-dir fails launchd EX_CONFIG while daemon status reports running
Opened by magistr · 7/26/2026· Shipped 7/26/2026
swamp worker daemon enable writes the --cache-dir value verbatim into the generated
service definition's WorkingDirectory and never creates the directory. Two consequences,
both silent:
- A relative
--cache-dirproduces a relativeWorkingDirectory, which launchd rejects. - An absolute but non-existent
--cache-dirfails the same way.
In both cases the job never runs (last exit code = 78: EX_CONFIG), the worker never enrolls
— and swamp worker daemon status --user still reports running / Enabled: yes, so the
operator has no signal that anything is wrong.
Reproduce (macOS, swamp 20260725.011748.0-sha.bb2cb3ef)
swamp worker daemon enable ws://127.0.0.1:9321 --user \
--token <enroll>.<secret> --server-token <admin>.<secret> \
--cache-dir ./daemon-cache --label spike=1
swamp worker daemon status --user
# Status (user service): running
# Enabled: yes
launchctl print gui/$(id -u)/club.swamp.worker
# state = spawn scheduled
# last exit code = 78: EX_CONFIG
swamp worker list --server ws://127.0.0.1:9321 --token <admin>.<secret>
# {"workers": [], "count": 0}The generated ~/Library/LaunchAgents/club.swamp.worker.plist contains:
<key>WorkingDirectory</key>
<string>./daemon-cache</string>Passing an absolute path whose directory does not yet exist fails identically. Creating
the directory first and re-running enable (or launchctl kickstart) makes the worker enroll
normally — confirming the path handling is the only fault.
Expected
Any of, in rough order of preference:
enablecreates the cache directory (it already owns the machine-id file that lives there);enableresolves--cache-dirto an absolute path before writing the service definition, and rejects a path it cannot create with an actionable error;daemon statusreports the real launchd/systemd job state (includinglast exit code) rather than "running" for a job that is only scheduled to spawn.
The last point is the one that costs the most debugging time: status actively contradicts the failure, so the natural next step (check the worker list, find nothing, suspect enrollment or tokens) leads away from the actual cause.
Notes
Found while building an agent-driven client that installs the managed worker daemon on a
customer's machine; the client now absolutizes and mkdir -ps the cache directory before
calling enable, which is a reliable workaround. Tokens are handled well otherwise — they go
into the service definition's EnvironmentVariables at mode 0600, never on argv.
Shipped
Click a lifecycle step above to view its details.