Background session's state.json keeps a stale inFlight.queued: 1, so the daemon never retires the idle session
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
A background session's state.json keeps inFlight.queued: 1 after the session drains its queue, and the daemon never retires that session's process because of it. Nothing is queued; the count is stale.
The in-flight snapshot is published from a component that reads the queue length while rendering, sessionCrons:!1}),L=Cu().getMainThreadQueueLength() in 2.1.301, without subscribing to the queue. It re-renders only when background tasks or todos change. When a background task finishes, its state change and its queued task notification land together, so that render sees 1. The notification is then dequeued, to start a wake-up turn or folded into a running turn, and nothing renders again, so 1 is written into every later state.json update. Another consumer in the same binary subscribes correctly: Rt(Cn.subscribe,()=>Cn.getMainThreadQueueLength()>0).
The daemon reads that field as work in flight. retireIfSettled returns {retired:!1,reason:"inflight"} when (n.inFlight?.queued??R)>0, which blocks idle retirement, the low-memory shed and the pinned-session pass. The stale-version retirement requires queued===0, and respawnIfIdleStale refuses too, so the session also never moves onto a newer binary.
On my machine, two background sessions idle for days still have their processes:
done/idlesince 2026-10-11 22:11 UTC,queued:1, ~430 MB.blockedsince 2026-10-08 01:08 UTC,queued:1, still on 2.1.293, ~420 MB.
Settled sessions with queued:0 and comparable idle times were retired on schedule; on 2026-10-13 14:30 UTC the daemon retired four of them, idle 13–16 h, and skipped the first session above.
What Should Happen?
inFlight.queued reports the queue as it is when state.json is written, returning to 0 once the notification is consumed. An idle, settled background session is retired after its grace period.
Error Messages/Logs
state.json of a probe session after its wake-up turn (2.1.296):
"inFlight":{"tasks":0,"queued":1,"kinds":[],"drainableMonitors":0}
A control probe with no background work ended at "queued":0. A probe whose notification was folded into a running turn and that then ran a 25 s foreground command ended at "queued":0: a later task change re-rendered the component.
Steps to Reproduce
- Start a background session (
claude --bg) and ask it to runsleep 20withrun_in_background: trueand end its turn. - When the command finishes, the session wakes up and ends its turn again.
- Read
~/.claude/jobs/<id>/state.json:inFlight.queuedis 1 and stays 1. - Leave it idle past the retirement grace period: its process keeps running, and
claude agents --jsonkeeps listing it with a live pid.
Claude Model
Sonnet
Is this a regression?
I don't know
Last Working Version
_No response_
Claude Code Version
2.1.301 (code read); measured on 2.1.296
Platform
Anthropic API
Operating System
Other Linux
Terminal/Shell
Other
Additional Information
Arch Linux. #92264 mentions a live job holding {tasks:0, queued:1, kinds:[]} in passing; #99931 and #87891 report background workers that are never retired, which may be this.