API Error 400 "tool use concurrency issues" caused by orphan tool_result blocks after context compaction
Description
After a long, tool-heavy session, Claude Code starts returning API Error: 400 due to tool use concurrency issues on every new message. The session becomes completely unrecoverable — even /rewind doesn't fix it.
Root Cause (from JSONL analysis)
The conversation's JSONL file contains orphan tool_result blocks — user messages with tool_result entries that reference tool_use IDs which no longer exist in any preceding assistant message. The Anthropic API correctly rejects this as invalid input (every tool_result must have a matching tool_use in a prior assistant message).
11 orphan tool_result references were found scattered across the conversation history, while all 32 resolved tool_use/tool_result pairs were properly matched. This means the assistant messages containing those 11 tool_use blocks were removed at some point, but the corresponding user messages with tool_result blocks were not.
How It Happened
- Long session with heavy tool usage (~32+ tool calls including Bash, Read, Grep, Glob, Agent, ToolSearch, and MCP tools)
- At some point, context management (likely auto-compaction) removed assistant messages containing
tool_useblocks - The paired user messages containing
tool_resultblocks for those same IDs were not removed - This created an invalid message history where
tool_resultblocks reference non-existenttool_useIDs - On the next API call that included these orphaned messages, the API returned 400
- Every subsequent message also fails because the corrupted history is still sent
Reproduction Context
- Claude Code version: 2.1.86
- Model: claude-opus-4-6 (also used claude-sonnet-4-6 during the session)
- Platform: macOS (Darwin 25.4.0)
- Session characteristics:
- ~130 JSONL entries
- 32+ tool calls (Bash, Read, Grep, Glob, Agent subagents, ToolSearch, MCP tools)
- Background agents were used (task-notifications present)
- Session was exported and resumed at one point (but export is read-only, shouldn't affect state)
/compactwas not manually triggered — compaction happened automatically
Evidence from JSONL
The /context command output showed:
claude-opus-4-6 · 16k/200k tokens (8%)
Compact buffer: 3k tokens (1.5%)
The low 8% usage with a compact buffer present confirms auto-compaction had already occurred. The queue-operation entries (enqueue/dequeue) appear immediately before the first error, suggesting possible timing issues.
The error message in the JSONL:
{
"type": "assistant",
"message": {
"role": "assistant",
"content": [{"type": "text", "text": "API Error: 400 due to tool use concurrency issues."}]
},
"error": "invalid_request",
"isApiErrorMessage": true
}
Expected Behavior
When context compaction removes an assistant message containing tool_use blocks, it should also remove the corresponding user message(s) containing the paired tool_result blocks — maintaining valid tool_use/tool_result pairing at all times.
Workaround
Starting a new session (/clear) is the only workaround. /rewind does not help because the orphan tool_result blocks are deep in the conversation history, not in the last turn.
This issue has 6 comments on GitHub. Read the full discussion on GitHub ↗