Claude Computer Use — Bash Tool Timeout
Claude called the bash tool for a long-running command (npm install, pytest, build) and your executor timed out. Fix: increase timeout for known-slow commands, stream stdout to detect hangs, or run in background and poll status.
Use subprocess.Popen with a streaming reader and a heartbeat check instead of blocking subprocess.run(timeout=N). For truly long tasks (installs, builds, migrations), start with nohup in the background, return the PID, and let Claude poll status with subsequent bash calls.
The Error Symptoms
subprocess.TimeoutExpired: Command 'npm install' timed out after 30s → Real install needs 2-5 minutes; default timeout too short Command hangs indefinitely — no output, no exit → Waiting for stdin (interactive prompt) with no TTY TimeoutError in asyncio.wait_for(...) → Async wrapper enforced its own timeout Claude keeps retrying the same command → tool_result contained "timeout" but no output; Claude assumes broken Zombie processes left after timeout → Didn't kill process tree; child processes orphaned Output truncated at ~10KB → Buffer limit; long output lost
What Actually Causes This Error
subprocess.run(capture_output=True) waits for process end. Long output = long wait.Fixes That Work (Tested Nov 2026)
1Streaming Bash Executor with Adaptive Timeout
2Command-Specific Timeout Presets
3Background Long Tasks with Polling
Claude's context handles polling naturally: "I started the build; let me check progress." Poll every N screenshots. This mimics how a human works: kick off a build, do other things, check periodically. Much better than blocking the whole conversation on a 20-minute Docker build.
Preventing This Error Going Forward
- Never use blocking
subprocess.run(timeout=30)for real workloads. Streams + Popen only. - Kill process groups, not single processes. Use
preexec_fn=os.setsid+os.killpg. - Always return partial output on timeout. Empty result confuses Claude.
- Detect interactive hangs. Use
</dev/nullor-yflags where possible. - Cap output at 10KB. Long build logs waste tokens; keep tail.
- For 5+ minute tasks, use background pattern. Poll status via subsequent tool calls.
Researcher · AI Error Hub
Frequently Asked Questions
You can expose a timeout parameter Claude can override, but sensible defaults per command pattern (install/build/test) are safer. Claude may not know that docker build can take 20 minutes.
Don't run them from bash tool — they need a TTY. Use the computer tool for GUI editors, or filter them out ("this command requires interactive terminal, not supported"). Guide Claude to use non-interactive equivalents (less --quit, top -bn1).
Yes if you expose a kill_background(job_id) tool. Implement with os.killpg(pid, signal.SIGTERM). Give Claude 10 seconds to complete cleanup, then SIGKILL.
Binary in stdout breaks the tool_result JSON. Redirect binary output to files, then return path/size/first-bytes summary. Never send raw binary to Claude.
Simpler for quick wraps: timeout 60 npm test. But you lose streaming output and don't detect idle hangs. Use it for simple cases; the Python approach for anything sophisticated.
Related Errors
Ship Robust Agent Systems
Weekly deep dives on subprocess management, background jobs, and computer-use reliability. 12,000+ developers subscribe.
Subscribe Free →