Claude Parallel Tool Use — Execution Errors
Claude returned multiple tool_use blocks in one response but your code only handles one. Or you need Claude to call tools sequentially and it's parallelizing. Fix: iterate all tool_use blocks and execute concurrently in your code, or use disable_parallel_tool_use.
Claude may emit multiple tool_use blocks in a single assistant message when tools are independent. Iterate ALL of them, execute concurrently (asyncio.gather / Promise.all), and return ALL tool_results in one user message. To force sequential: set tool_choice: {type: "auto", disable_parallel_tool_use: true}.
The Symptoms You're Seeing
Claude returned 3 tool_use blocks; my code called only the first → Result: missing tool_result IDs → next API call fails Error: "tool_result for tool_use_id toolu_02 is missing" → You returned only 1 tool_result but Claude expects N Agent slow because tools run one at a time → Concurrent execution possible; code doesn't take advantage Race conditions when tools share state (writing to same file) → Parallel tools have dependency; must serialize Second tool result depends on first tool's output → Claude split into two turns but should have chained
How Parallel Tool Use Works
When Claude sees multiple independent tools it could call, it may emit them all in one response. Your job is to execute them (in parallel for speed) and return all results. Claude only chains sequentially when later calls depend on earlier ones — that's automatic based on Claude's understanding.
What Actually Causes This Error
Fixes That Work (Tested Nov 2026)
1Iterate All tool_use Blocks, Execute in Parallel
2Force Sequential With disable_parallel_tool_use
The disable_parallel_tool_use flag can pair with all tool_choice modes: auto, any, or {type: "tool", name: "specific"}. Useful when you want to force a specific tool AND ensure only one call per turn.
3Handle Shared State With Locks
Preventing This Error Going Forward
- Always iterate ALL tool_use blocks. Never assume one per response.
- Use asyncio.gather / Promise.all for concurrency. Free performance win.
- Add locks around shared state. Prevents race conditions.
- Force sequential when order matters. Use disable_parallel_tool_use for workflows.
- Return one result per tool_use. IDs must match; count must match.
- Use return_exceptions=True. One failure shouldn't kill the whole batch.
Researcher · AI Error Hub
Frequently Asked Questions
Usually yes, but not guaranteed. Claude's decision depends on the task. Some models parallelize more aggressively than others. Test empirically for your workload; use disable_parallel_tool_use if you need deterministic behavior.
No. Each tool_use is generated during Claude's output. Whether they're in one response (parallel) or spread across turns (sequential) doesn't change token cost — the tokens are identical either way.
API rejects the request with 400. Every tool_use_id must have a matching tool_result. If a tool fails, return an error result with is_error: true — don't skip.
Yes. Order in the array doesn't matter — Claude matches by tool_use_id. But it's conventional to return them in the same order for readability.
You'll see multiple content_block_start events for tool_use blocks. Wait for all content_block_stop events to have complete inputs, then execute all in parallel. Don't kick off tools mid-stream.
Related Errors
Ship Fast, Reliable Tool Agents
Weekly deep dives on parallelism, tool patterns, and agentic workflows. 12,000+ developers subscribe.
Subscribe Free →