Commands that hit the Bash timeout keep running in the background unbounded; agents re-run them and processes pile up until the host runs out of memory

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

Environment: Claude Code 2.1.284, Linux (Ubuntu 24.04, 16 cores / 30 GB RAM / 8 GB swap), several interactive sessions using subagents.

This is documented behaviour ("When a command reaches its timeout without finishing, Claude Code moves it to the background instead of stopping it", tools-reference § Bash tool behavior), but it has a failure mode that took a host down twice, so I'm reporting it with some requests.

What happened

A code change introduced an infinite render loop, so a project's full vitest suite never finishes and grows by about 2.5 GB/min across its 8 fork workers (when a worker hits the V8 heap limit, vitest spawns a replacement that loops again).

A subagent ran the full suite. At the 120 s timeout it was moved to the background rather than stopped. The agent carried on and later ran the same suite again, which was also backgrounded. Nothing told the agent that an identical earlier run was still going.

  • Incident 1: three such runs overlapped and filled 30 GB RAM + 8 GB swap in about 40 minutes. The kernel OOM killer then killed the user's systemd --user, ending every session.
  • Incident 2 (next morning): the agent started the suite twice more, the second time with run_in_background and no limit, then ended its turn "until it finishes". Other sessions' healthy test suites slowed, hit their own timeouts, were backgrounded and were re-run, adding load. Memory reached 96% and swap 100% with no OOM kill; the host stayed pingable but could not complete an SSH login for ~2 hours and needed a physical power cycle.

Why this is a problem

  • A timeout no longer limits anything: a command that never finishes runs until the machine dies.
  • Agents read "moved to the background" as "slow, carry on", so retrying turns one runaway into several.
  • There is no limit on concurrent background tasks and no link between a new command and an identical one still running.

Reproduce (verified)

  1. In a Bash tool call with a short timeout, run a process that keeps allocating:

node -e 'const a=[];setInterval(()=>{a.push(Buffer.alloc(5e6).fill(1));},100)'

  1. It is reported as "moved to the background" at the timeout and keeps growing (measured 589 MB → 790 MB over the next 4 s) until manually stopped.
  2. Ask the agent to "run it again, it seemed to time out": a second copy starts alongside the first.

Requests

  1. A setting to kill on timeout that leaves deliberate background tasks alone. CLAUDE_CODE_DISABLE_BACKGROUND_TASKS is currently the only lever and disables everything.
  2. A limit on concurrent background tasks, and/or a warning when a new command matches one still running from this session or subagent.
  3. Give auto-backgrounded commands their own hard limit, or at least show elapsed time and memory in the task list so a runaway is visible.
  4. Make the timeout message tell the model the command is still running and consuming resources, so it doesn't start another copy.

Related (background-task cleanup, not this pile-up): #83627, #92583, #95242

View original on GitHub ↗

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