Bash run_in_background ignores `timeout` and a never-exiting background task produces no notification
Summary
Two related gaps in the Bash tool's background mode:
timeoutis not applied whenrun_in_background: true. A backgrounded command runs until it exits on its own; the declared deadline is ignored.- A background task that never exits produces no notification, ever. There is no idle-task or deadline notification, so a session that ended its turn waiting on that task is never re-entered.
Together these turned a malformed polling loop into a ~10-hour stall: the session ended its turn "waiting for the background task", the task could never exit, and nothing woke the session until a human typed.
Environment
- Claude Code 2.1.236 and 2.1.239 (macOS, Darwin 25.x, node 22 and 26)
- Reproduced on two hosts on 2026-08-21
Repro
Bash tool call:
{"command": "sleep 90; echo done", "run_in_background": true, "timeout": 5000}
Expected: the task is killed at ~5 s and the completion notification reports a timeout.
Actual: the task runs the full 90 s and completes with exit 0; the timeout value has no effect.
Second observation (same day): a backgrounded until gh api ... ; do sleep 30; done whose condition could never succeed (invalid flags, stderr suppressed) was still running 13 hours later; ps showed the zsh child alive and polling. The session had declared timeout: 600000 on it. No notification was ever delivered for the task, so the session never resumed.
Suggested fix
- Enforce
timeouton background tasks the same way as foreground tasks (kill the process group at the deadline and deliver a completion notification that says it timed out). - Failing that, deliver a notification when a background task exceeds its declared
timeout(or a default ceiling) so the model can react.
Workaround in use
A PreToolUse hook that denies backgrounded while/until loops with no in-command deadline (timeout/gtimeout wrapper or bounded iteration), and an orchestration rule to always pair a background wait with a persistent Monitor plus a CronCreate fallback.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗