Session corruption: orphaned tool_use/tool_result entries cause unrecoverable 400 concurrency error
Session corruption: orphaned tool_use/tool_result entries cause unrecoverable "API Error: 400 due to tool use concurrency issues"
Description
A long-running session (~3100 JSONL lines, ~27MB) became permanently unrecoverable after pasting 8 base64 images in a single message. Every subsequent prompt — including after multiple /rewind attempts and claude --resume — returns:
API Error: 400 due to tool use concurrency issues. Run /rewind to recover the conversation.
Root cause
Analysis of the JSONL conversation file revealed orphaned tool_use/tool_result pairs scattered throughout the history:
| Line | Issue | Details |
|------|-------|---------|
| L2 | tool_result with no matching tool_use | References a toolu_* ID that doesn't exist in the file |
| L762 | tool_use with no matching tool_result | Bash call — no result ever recorded |
| L2275 | tool_use with no matching tool_result | Bash call — no result ever recorded |
Stats: 714 tool_use entries, 713 tool_result entries, 2 orphan uses, 1 orphan result.
These orphaned entries produce an invalid API request when the conversation is replayed (tool_use without a following tool_result violates the API's message structure requirements).
Why /rewind doesn't help
/rewind removes the last user/assistant exchange pair from the tail of the conversation. But the orphaned entries are at L2, L762, and L2275 — deep in the history. No amount of rewinding can reach them without destroying the entire session.
Trigger
The error first appeared when pasting a user message containing 8 base64-encoded PNG screenshots (~3.5MB total). The submission produced two consecutive user lines in the JSONL:
- L3031: user message with text + 8 base64 image content blocks
- L3032: a second user message with 8 text blocks containing
[Image: source: /path/to/file.png]path references
This double-user-message is itself invalid, but even after manually removing it, the session remained broken due to the pre-existing orphaned tool entries listed above.
Reproduction
Not easily reproducible on demand, but the conditions were:
- Long session with heavy tool use (~714 tool calls, multiple context compactions)
- Session continued from a previous conversation that ran out of context (visible at L2735)
- Multiple parallel tool calls throughout (normal Claude Code behavior)
- Large multi-image paste as the triggering event
Suggested fixes
- JSONL serializer: Ensure every
tool_usegets a correspondingtool_resultwritten, even if the tool call was cancelled, timed out, or errored. Write a synthetic error result if needed. - Session replay: Validate tool_use/tool_result pairing when loading a session. Inject synthetic results for orphaned uses, and drop orphaned results, before sending to the API.
- Image handling: Don't split a single user submission into two separate
userJSONL entries (the base64 images and the path metadata should be one entry). - Better /rewind: When the 400 error occurs, offer a deep repair option that scans and fixes structural issues, rather than only trimming the tail.
Environment
- Claude Code CLI (latest as of 2026-03-26)
- macOS Darwin 25.4.0
- Session file: ~27MB, ~3100 lines, 714 tool calls
5 Comments
Found 3 possible duplicate issues:
This issue will be automatically closed as a duplicate in 3 days.
🤖 Generated with Claude Code
This is a regression in version 2.1.85. Downgrading to 2.1.84 (through some
install_claude.shtweaking) has got me working again. It's reproducible in multiple conversations that were working fine in 2.1.84 and now fail with this error in 2.1.85. I do not see any mismatched tool_use/tool_results in my context either.Orphaned tool_use/tool_result pairs deep in session history are exactly what Cozempic's
corrupted-tool-usedoctor check is built to catch. The 400 'due to tool use concurrency issues' is the tell.cozempic doctorwill scan the full JSONL (not just the tail) and flag mismatched pairs anywhere in the history.cozempic treatthen runs afix_orphaned_tool_results()repair pass that surgically patches the structural corruption — we've recovered sessions with orphaned pairs at line 2 of a 3,100-line file.We built Cozempic after losing a production session to this same bug. Leaving this here in case others hit it — the repair works even on sessions where
/rewindcan't reach the corruption.Yes, I've seen a few tools offer to do this, but having tried another one, there are no mismatched tool_use/tool_results. My native Claude Code auto-updated itself to 2.1.85 again and the bug is back.
This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.