Bash tool permanently broken (exit 1, no output) after a killed background task

Resolved 💬 1 comment Opened May 28, 2026 by nmdesai Closed Jun 28, 2026

Summary

Bash tool becomes permanently broken (every invocation returns exit code 1 with no stdout/stderr) after a long-running background Bash task is killed by the harness for exceeding its timeout. The tool's persistent session state appears to be torn down with the killed process and never recovers; only restarting the Claude Code session restores Bash. All other tools (Read, Write, Edit, etc.) continue to work normally.

Steps to reproduce

  1. Launch a Bash invocation with run_in_background: true and a polling loop that runs longer than the configured timeout. For example:

``bash
# Bash tool call, timeout: 240000 ms, run_in_background: true
launchctl start com.user.water-meter
for i in 1 2 3 4 5 6 7 8 9 10 11 12; do
state=$(launchctl print "gui/$(id -u)/com.user.water-meter" 2>&1 \
| grep "^ state =" | head -1 | awk '{print $3}')
echo "[$i] state=$state"
[ "$state" = "not" ] && break
sleep 10
done
``

  1. The harness eventually kills the task; the task-notification arrives with <status>killed</status>.
  1. From that point on, ANY subsequent Bash invocation in the same session — even echo hi — returns exit code 1 with completely empty output (no stdout, no stderr).

Expected behavior

A killed background task should not leave the Bash tool in an unrecoverable state. Either:

  • Subsequent Bash invocations should spin up a fresh shell as if nothing happened, or
  • The tool should surface a clear error explaining what happened and suggest a remedy.

Actual behavior

> echo alive
(Exit code 1)
> ls
(Exit code 1)
> pwd
(Exit code 1)
> date
(Exit code 1)

No output at all. The tool returns "Exit code 1" with no body, even with dangerouslyDisableSandbox: true. The only fix is to terminate Claude Code and start a new session.

Diagnostics gathered before reporting

  • Verified no project hooks: ~/.claude/settings.json only has theme + marketplace, no hooks block. Project repos have no .claude/settings.json.
  • Checked the per-session CWD tracking file referenced in earlier successful Bash invocations (e.g., /tmp/claude-84c9-cwd from a prior pwd -P >| /tmp/claude-<id>-cwd line in the wrapped shell). The file no longer exists — Read reports "File does not exist". This is consistent with the persistent shell process having been killed alongside the polling loop.
  • Other tools work fine in the same session (Read, Write, Edit, ScheduleWakeup, ToolSearch).
  • Tried dangerouslyDisableSandbox: true — still exit code 1, no output.

The failure mode is silent: there is no indication to the model that the tool is broken until it tries to run something. A model under time pressure could spend many turns retrying or "debugging" a permanently-broken tool.

Environment

  • macOS Tahoe (26.0) on Apple Silicon
  • mosh-over-Tailscale → SSH → tmux → claude (kiosk-like persistent session)
  • Session was long-running (~12 hours) before the kill

Suggested mitigations

  1. Detect this state and surface a clear error (e.g., "Bash tool state lost after background task termination — start a new session or run /reset-tool-state").
  2. Recover automatically by spawning a fresh persistent shell on the next invocation.
  3. Avoid coupling the persistent shell's lifetime to any individual background-task process group.

Workaround used during the session

Wrote shell scripts to /tmp/*.sh via the Write tool and asked the user to invoke bash /tmp/<script>.sh from a Terminal on the host. Awkward for an iPad user (no easy copy/paste from the Claude Code terminal) but unblocked finishing the work.

View original on GitHub ↗

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