claude-code - 💡(How to fix) Fix Parallel tool calls: one benign tool error cancels all sibling calls → agent misreads as broken shell and flails

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

When an assistant turn emits multiple parallel tool calls and any single call returns an error, Claude Code cancels all still-pending sibling calls in that batch. Each cancelled call returns a tool result whose text is Cancelled: parallel tool call Bash(<X>) errored. The triggering error is frequently benign (a grep that matched nothing → exit 1, a Read of a missing path, a TaskCreate with a missing field). Because trivial commands like echo hello and pwd then come back marked as errors, the model misreads it as a broken shell and spirals into diagnostic probing — and since it issues the probes in batches too, they get cancelled by the next failing sibling, producing a self-reinforcing flailing loop that burns large amounts of time and tokens for zero progress.

Error Message

When an assistant turn emits multiple parallel tool calls and any single call returns an error, Claude Code cancels all still-pending sibling calls in that batch. Each cancelled call returns a tool result whose text is Cancelled: parallel tool call Bash(<X>) errored. The triggering error is frequently benign (a grep that matched nothing → exit 1, a Read of a missing path, a TaskCreate with a missing field). Because trivial commands like echo hello and pwd then come back marked as errors, the model misreads it as a broken shell and spirals into diagnostic probing — and since it issues the probes in batches too, they get cancelled by the next failing sibling, producing a self-reinforcing flailing loop that burns large amounts of time and tokens for zero progress. Across the session, 31 of 36 total tool errors were this cancellation cascade, seeded by only ~5 genuine (and benign) errors. Grouping tool_use by message.id confirmed the trigger is a genuine sibling error, not batch size or any specific tool: a 9-call batch with one error cancelled 5 siblings; an 18-call batch with zero errors cancelled nothing.

Root Cause

When an assistant turn emits multiple parallel tool calls and any single call returns an error, Claude Code cancels all still-pending sibling calls in that batch. Each cancelled call returns a tool result whose text is Cancelled: parallel tool call Bash(<X>) errored. The triggering error is frequently benign (a grep that matched nothing → exit 1, a Read of a missing path, a TaskCreate with a missing field). Because trivial commands like echo hello and pwd then come back marked as errors, the model misreads it as a broken shell and spirals into diagnostic probing — and since it issues the probes in batches too, they get cancelled by the next failing sibling, producing a self-reinforcing flailing loop that burns large amounts of time and tokens for zero progress.

Code Example

<tool_use_error>Cancelled: parallel tool call Bash(echo "=== plans dir ===" && ls -la docs/) errored</tool_use_error>
RAW_BUFFERClick to expand / collapse

Summary

When an assistant turn emits multiple parallel tool calls and any single call returns an error, Claude Code cancels all still-pending sibling calls in that batch. Each cancelled call returns a tool result whose text is Cancelled: parallel tool call Bash(<X>) errored. The triggering error is frequently benign (a grep that matched nothing → exit 1, a Read of a missing path, a TaskCreate with a missing field). Because trivial commands like echo hello and pwd then come back marked as errors, the model misreads it as a broken shell and spirals into diagnostic probing — and since it issues the probes in batches too, they get cancelled by the next failing sibling, producing a self-reinforcing flailing loop that burns large amounts of time and tokens for zero progress.

Evidence (from a real session)

A single assistant turn issued 27 parallel tool calls. One was echo "=== plans dir ===" && ls -la docs/plans/ | grep -i "..." — the grep matched nothing and exited 1. That one benign exit caused 26 sibling calls to be cancelled, including pwd, echo hello, and printf 'literal-output-test\n'; true (which cannot exit non-zero). All 26 returned:

<tool_use_error>Cancelled: parallel tool call Bash(echo "=== plans dir ===" && ls -la docs/…) errored</tool_use_error>

Across the session, 31 of 36 total tool errors were this cancellation cascade, seeded by only ~5 genuine (and benign) errors. Grouping tool_use by message.id confirmed the trigger is a genuine sibling error, not batch size or any specific tool: a 9-call batch with one error cancelled 5 siblings; an 18-call batch with zero errors cancelled nothing.

Impact

  • Severe, silent token/time waste. The model cannot distinguish a cancelled sibling from a real failure, concludes the environment is broken, and flails (re-running commands, emitting echo/pwd probes, defensively duplicating commands within a batch). Sessions can burn dozens of tool calls and hundreds of thousands of tokens recovering.
  • Misdiagnosis. The behavior looks like model degradation or a broken shell; it is neither. It took an extended investigation to trace it to this mechanism.
  • Amplified under auto-approval / per-call permission classification, which serializes a batch and keeps siblings pending longer (wider cancellation window).

Expected behavior

A benign non-zero exit in one parallel call should not silently cancel unrelated sibling calls; or, if cancellation is intended, the cancellation result should be worded so it is unmistakably not an environment failure and instructs re-running the single call — so the model recovers instead of flailing.

Actual behavior

Sibling calls are cancelled and surfaced with Cancelled: parallel tool call X errored, which reads to the model as a catastrophic/broken-shell signal.

Suggested fixes (any one would help)

  1. Don't cancel siblings on a benign non-zero exit — let each parallel Bash call resolve independently; a grep exit-1 in call A shouldn't abort call B.
  2. Reword the cancellation result to explicitly say a sibling errored, the environment is fine, and the call can simply be re-run alone. (Cheapest fix; directly stops the misinterpretation.)
  3. Expose disable_parallel_tool_use as a Claude Code setting / env var (it exists on the API tool_choice but isn't surfaced in Claude Code).
  4. Fire a hook event for cancelled calls so users can build their own corrective context injection (PostToolUse currently does not fire for cancelled calls and does not receive result text, so this can't be mitigated via hooks today).

Environment

  • Claude Code: 2.1.159
  • Model: claude-opus-4-8 (1M context)
  • OS: macOS (darwin 25.4.0)
  • Mode: auto-approval (skipAutoPermissionPrompt) with PreToolUse hooks present

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

A benign non-zero exit in one parallel call should not silently cancel unrelated sibling calls; or, if cancellation is intended, the cancellation result should be worded so it is unmistakably not an environment failure and instructs re-running the single call — so the model recovers instead of flailing.

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

claude-code - 💡(How to fix) Fix Parallel tool calls: one benign tool error cancels all sibling calls → agent misreads as broken shell and flails