[BUG] agents view: re-hosting a reaped background session always crashes once ("Session ... is currently running as a background agent" -> exit_with_message), ~10s penalty per open

Resolved 💬 1 comment Opened Jul 4, 2026 by joevon Closed Jul 5, 2026

Summary

Opening a background-agent chat in the claude agents view (FleetView) whose worker was previously reaped shows:

[worker crashed (exit 1 — exit_with_message) — respawning…]

and takes ~10 seconds before the respawn succeeds. This happens on every open of a session whose worker isn't currently live (the supervisor reaps workers after ~1h unattached), so in practice almost every chat open pays the 10s penalty. Foreground claude --resume <session-id> of the exact same session works instantly, every time.

The actual dying message (root cause candidate)

The worker's exit message is visible in the pty right before the crash banner:

Session <session-id> is currently running as a background agent (bg). Use `claude agents` to find and attach to it, or add --fork-session to branch off a copy.

[worker crashed (exit 1 — exit_with_message) — respawning…]

So this looks like a self-deadlock in the re-host path: the supervisor claims a spare worker to resume session X (bg claimed-spare <short> (fleet), dispatch launch.mode: "resume"), the worker's "is this session already running as a bg agent?" guard finds the session's own job record (the very job it was dispatched to serve), prints the message above, and exits 1 (exit_with_message). The supervisor respawns; attempt: 2 in roster.json then succeeds. The user-visible cost is the crash banner + ~10s on every open.

Evidence

~/.claude/daemon.log — reap of sessions that were actually blocked/waiting (not done), later re-host on open:

[...T15:54:22] [bg] bg settled 91450b88 (done)      <- session was blocked on user input, worker reaped
[...T16:16:22] [bg] bg settled 7e5977c8 (done)      <- same
[...T18:23:26] [bg] bg claimed-spare 7e5977c8 (fleet)   <- user opens chat in agents view -> crash banner, ~10s, then OK

~/.claude/daemon/roster.json for the affected worker after the crash cycle shows "attempt": 2 with dispatch:

"dispatch": {
  "source": "fleet",
  "launch": {
    "mode": "resume",
    "sessionId": "<session-id>",
    "fork": false,
    "flagArgs": ["--agent", "claude", "--model", "claude-fable-5[1m]", "--permission-mode", "plan"]
  }
}

Ruled out

  • Not fixed by a daemon restart: claude daemon stop --any --keep-workers + fresh daemon → same crash on next re-host.
  • Not version skew: reproduced with daemon and worker both on 2.1.200, and again on 2.1.201 after the overnight self-upgrade.
  • Not hooks: SessionStart/Stop hooks run headless in <0.2s with exit 0.
  • Not the statusLine command: reproduced with statusLine removed from settings.json.
  • Racy, not deterministic: a supervisor-initiated respawn of a killed worker succeeded on its first attempt with the same job record present — the guard only sometimes loses the race.
  • Not transcript size: affected session transcript is 2 MB.
  • Not the model flag: claude -p --model 'claude-fable-5[1m]' works standalone.
  • Foreground path clean: claude -p --fork-session --resume <session-id> completes in ~14s total including model turn; interactive claude --resume <session-id> attaches in ~1s with no crash.

Expected

The dispatched resume worker should be exempt from (or should win) the "session is already running as a background agent" guard when the session's bg job is the one it was dispatched to host — first attempt should succeed, no crash banner, no 10s delay.

Environment

  • Claude Code 2.1.200 and 2.1.201 (both reproduce)
  • macOS (Darwin 25.5.0), arm64
  • Daemon origin: transient (started on demand by claude agents)

Possibly related: #59653 (closed), #59652 — same "worker crashes then respawns" symptom class, but this report pins the exact exit message and the self-lock mechanism.

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗