[BUG] Auto-update daemon transition reaps a live session's in-flight headless background tasks (status 'killed', no attribution) — Linux, 2.1.210→2.1.211

Status Fixed / completed
Reported on v2.1.211
Maintainer reply ✓ Yes — bcherny
Activity 4 comments · opened Jul 16, 2026 · closed Aug 17, 2026
💡 Likely answer: A maintainer (bcherny, collaborator) responded on this thread — see the highlighted reply below.

Environment

  • Claude Code on Linux, native install
  • A long-lived daemon-managed background session (agents view job), process running v2.1.210
  • Auto-update installed v2.1.211 while the session was mid-work

What happened

Two background tasks spawned by the session's Bash tool (each a timeout 5400 claude -p --model sonnet ... headless run, launched with run_in_background) were killed 1-3 minutes after launch, with task status "killed", zero bytes of output, and no TaskStop issued by the session. A third identical launch the next morning completed normally.

Forensic timeline (all times local):

  • 02:07 first headless task launched
  • 02:10 the auto-updater finished installing the v2.1.211 binary (~/.local/share/claude/versions/2.1.211 mtime is exactly 02:10)
  • ~02:10 first task killed; 02:10-02:11 second task launched
  • 02:11:10 daemon log: [supervisor] another daemon is already running (pid=..., version=2.1.211, origin=transient; an on-demand daemon never displaces a running one) followed immediately by [bg] bg orphan-spare reap: 1
  • ~02:12 second task killed
  • No OOM (plenty of free memory), no timeout (both tasks were minutes into a 90-minute budget), nothing in the system journal

Collateral pattern: the session itself and a long-running Monitor task (armed hours earlier) survived untouched. Only the freshly-spawned headless child processes died. An ephemeral, never-requested task also flashed in and out of the session's task directory during the same window, which I take to be the updater/daemon machinery itself.

Reading

During the auto-update daemon transition, the new (or surviving) daemon's orphan/spare reaping appears to sweep up in-flight claude -p child processes that belong to a live session's background tasks, treating them as orphans. The session gets a "killed" task notification with no attribution, which reads exactly like the unexplained kills in #76249.

Related, but not the same shape: #73670 (supervisor shuts down for auto-upgrade and never restarts, workers watchdog-killed), #66358 (post-update version skew orphans old workers), #73332 (workers reaped mid-work on macOS). In our case the daemon transition itself went fine and the session survived; the casualties were the session's own in-flight headless child tasks.

Expected

In-flight background tasks owned by a live session should survive an auto-update daemon transition (or at minimum be terminated with an attributable reason surfaced to the session, so the agent does not have to forensically reconstruct what killed its work).

Suggestion

  • Exempt processes that are registered children of live session tasks from orphan-spare reaping during the update transition, or
  • Hand them over to the new daemon the way adopted sessions are, or
  • If they must die, deliver a task notification that names the updater/daemon transition as the cause.

View original on GitHub ↗

3 Comments

gorkem2020 · 3 months ago

Follow-up with new evidence from the same host, which broadens the picture beyond the auto-update transition:

A second kill wave hit today at 17:13-17:21 local with NO update in play (no new binary since the 02:10 one, daemon log silent for hours). Three registered background tasks were stopped 2-5 minutes after launch, including a trivial 30-second-sleep watcher loop, so the trigger is not the task's content or cost. Two control datapoints from the same window:

  • A setsid-detached copy of the identical killed workload ran to completion untouched while its registered twin died. Registration with the task system is the fatal ingredient.
  • A registered canary re-test three hours later survived, so the kill rate is sporadic rather than absolute, and it clusters in waves.

This looks like the same family as #76974 (sporadic SIGKILL by task supervision) and #76942 (kills appearing only after a session runs long). Consistent with the latter: this session's job is 12 days old and the waves started after the process had been up ~11h, getting denser at ~26h. The auto-update daemon transition in my original report may be an aggravator or one trigger among several rather than the sole cause.

Practical impact for long-lived agent sessions is significant: in-flight work dies silently mid-task with status "killed" and no attribution, and the workaround (detaching work from the task system) costs the completion-notification machinery. A reap/stop audit line naming the killer (supervisor, watchdog, stop-routing, update transition) would make this class diagnosable in the field.

gorkem2020 · 2 months ago

New datapoint that isolates the collateral-stop mechanism from the process-age and version-skew vectors this issue documented so far, and cross-references #76249 (which looks like the same underlying reap).

Setup: daemon and session both on 2.1.211 (no skew), daemon ~22h old (no long-lived-process factor), Linux, healthy memory (7.7Gi available).

Sequence (UTC, from the session transcript):

  1. 16:05:41 - a run_in_background bash task starts (a CI polling loop with a 45 minute budget).
  2. 16:06:08 - TaskStop is called on an UNRELATED task: an in_process_teammate agent, correctly stopped by id.
  3. 16:06:31 - 23 seconds later, the 50-second-old background bash task from step 1 is reported killed with the harness's own stop wording (status: killed, summary: "was stopped"). No other task died; a long-running persistent monitor in the same session survived untouched.

Timeout, OOM, and the age/skew vector are all excluded (50s of a 45m budget; free memory; fresh aligned daemon). This looks like stop routing inside the shared per-job daemon task registry occasionally reaping a sibling, which matches #76249's no-TaskStop repro on 2.1.206: the registry reap may be the common mechanism, with TaskStop acting as one trigger among several.

Workaround we use for load-bearing watchers: launch them registry-independent (setsid nohup ... &, polling an output file) whenever a TaskStop may be issued in the same window, and keep all watchers idempotent so a reap never loses state.

bcherny collaborator · 1 month ago

Thanks for the detailed timeline — I tried to reproduce this on current released builds.

Setup: a daemon-managed background session on 2.1.210 (your original version) with an in-flight background task (run_in_background, 5-minute command), then an update to 2.1.233 installed mid-task. Note: 2.1.230 is no longer downloadable from the installer, which is why I started from 2.1.210.

The update was detected within seconds and the background service restarted onto the new version while the task was running. In three trials (session mid-turn, idle, and idle with nothing attached), the in-flight task kept running, completed on schedule, and produced its full output — it was never marked "killed". A control run without an update also completed.

Several background-service reliability fixes around updates shipped shortly after the 2.1.211 build you hit (see the 2.1.203–2.1.217 changelog entries about background sessions and updates), and current versions deliberately avoid restarting a session that has work in flight.

This looks fixed in current releases, so I'm closing it. If you see a background task killed around an auto-update on 2.1.233 or later, please reopen with the new timeline.

🤖 Generated with Claude Code

Showing cached comments. Read the full discussion on GitHub ↗