run_in_background reports a self-backgrounding command as completed instantly, orphaning the process

Status Open
Reported on v2.1.266
Maintainer reply None cached
Activity 1 comment · opened Sep 9, 2026

Environment

  • Claude Code 2.1.266
  • Linux 7.0.0-31-generic, 16 cores, 62.5 GB RAM
  • Node v24.19.0

What happens

A Bash tool call made with run_in_background: true, whose command itself ends
in &, is recorded as finished the moment the wrapper shell exits — not when the
work does. The real process keeps running, untracked.

The harness task record, in full, 48 bytes, written at 16:37:38:

suite lanzada PID 1214483

[exited with code 0]

That same PID 1214483 was still consuming 48.8% CPU 20 minutes later, and its
output file kept growing until 16:59:56, when it was killed by hand.

Reproduction

// Bash tool call
{ "command": "nohup sleep 600 > /dev/null 2>&1 & echo \"started, PID $!\"",
  "run_in_background": true }

Verified on 2.1.266. The task file is written immediately:

started, PID 1535938

[exited with code 0]

and a <task-notification> arrives saying completed (exit code 0) — while five
seconds later:

$ pgrep -af "sleep 600"
1535938 sleep 600

pkill was needed to reap it; it was not cleaned up by the harness.

Why it matters

The orphan is invisible and unaccounted:

  • it does not appear in /tasks, so neither the agent nor the developer can see it;
  • it has no CPU accounting or attribution;
  • it is not cleaned up when the session ends;
  • the agent believes the work is done and starts more.

That last point is what made this worth filing. In our session the agent launched
a full vitest suite (8397 files, ~1 worker per core), was told it had completed,
and 25 minutes later launched a second one. The two overlapped for ~21 minutes and
saturated all 16 cores:

16 cores:      69.9% – 92.5%   (every core)
Load average:  24.84  27.27  22.26
Mem:           31.3G / 62.5G          ← memory was never the constraint
Swp:           0K / 4.00G

Update (2026-09-10): the session interruptions we saw in that window were not
caused by the load. The orphaned suite's own tests were deleting the session's
credentials through an inherited CLAUDE_CONFIG_DIR (see the correction on
#93127; the test-suite fix is stablyai/orca#19889). That makes the orphaning worse,
not better: an untracked process kept running with the session's environment and
side effects no one could see, and because it had been reported as finished,
neither the agent nor the developer suspected it. The orphaning itself is
deterministic and reproducible, as shown above.

Suggested fix

Wait on the full process group rather than the wrapper shell, or detect a
self-backgrounding command and either refuse it or track the spawned PID so it
appears in /tasks and is reaped at session end.

Secondary observation (withdrawn)

An earlier version of this report attributed two temporarily unavailable errors
in that window to host load. They were authentication failures — the credentials
had just been deleted — so the observation is withdrawn; see #93127.

View original on GitHub ↗

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