Bash run_in_background ignores `timeout` and a never-exiting background task produces no notification

Status Open
Reported on v2.1.236
Maintainer reply None cached
Activity 1 comment · opened Aug 21, 2026

Summary

Two related gaps in the Bash tool's background mode:

  1. timeout is not applied when run_in_background: true. A backgrounded command runs until it exits on its own; the declared deadline is ignored.
  2. 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 timeout on 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.

View original on GitHub ↗

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