Agents daemon orphans old bg workers after auto-update → EAUTH: attach rejected (control-key version skew)
What happened
After Claude Code auto-upgraded the background agents daemon from 2.1.168 → 2.1.169 mid-session, opening the agents window (claude agents) failed to attach with:
Couldn't attach — EAUTH: attach rejected: this client didn't present the daemon control key — update Claude Code (old client?)
The "update Claude Code (old client?)" hint is misleading: the CLI client was already on the latest version (2.1.169). The orphaned parties are the background workers spawned by the previous daemon (2.1.168), which are cryptographically locked to the old control key and can't authenticate to the freshly-restarted daemon.
claude daemon status confirms the skew:
version: 2.1.169
bg workers: 8 running (control.sock), 8 in roster.json
5 from a different CLI version
holding this daemon open:
8 bg workers running (daemon waits for them to settle)
So 5 of 8 workers are from the prior version and cannot be attached, even though they are still alive and doing work.
Expected
When the daemon restarts due to a version change while background workers are still running, it should either:
- re-key / migrate existing workers to the new control key, or
- gracefully drain old-version workers (let them finish, keep them attachable) before/while adopting the new key, or
- at minimum accept attach from same-user workers it can identify, rather than hard-rejecting with
EAUTH.
Actual
The new daemon generates a fresh control key, and any worker started by the old daemon is permanently un-attachable for the remainder of its life. The only known recovery is killall -9 claude, which destroys in-flight background agent work — unacceptable when long-running sessions are mid-task.
Why this matters
Auto-update is on by default, so this happens silently to anyone who keeps background agents running across an update window. The user is forced to choose between losing in-flight work (killall -9 claude) or living with a broken agents window until every old worker finishes.
Repro
- Start one or more long-running background agents.
- While they run, let the binary auto-update (e.g.
2.1.168→2.1.169), which restarts the daemon. - Run
claude agents. - Observe
EAUTH: attach rejected: this client didn't present the daemon control key. claude daemon statusshowsN from a different CLI version.
Current workarounds (both poor)
killall -9 claude— kills the daemon and all workers, losing in-flight agent work.DISABLE_AUTOUPDATER=1— prevents the binary from swapping under running workers, but disables auto-update entirely and is opt-in/undiscoverable.
Suggested fixes
- Daemon worker re-key / handoff on version-change restart (preferred).
- Defer the daemon restart until no background workers are running (drain-then-upgrade).
- Make the error message accurate — point at "old background workers from a previous version" and suggest a non-destructive recovery, not "update Claude Code (old client?)".
Environment
- Claude Code
2.1.169(auto-upgraded from2.1.168) - macOS (Darwin 25.3.0)
- Multiple
claude agentswindows open across separate repos; 8 bg workers, 5 from the prior version.
This issue has 5 comments on GitHub. Read the full discussion on GitHub ↗