Diagnosing and Fixing the Recurring "The model's tool call could not be parsed" Error in Claude Code
Hello! This is the Qualiteg Product Development Team.
While developing with Claude Code (CLI), we ran into a phenomenon where the following error appeared repeatedly and brought work to a halt.
● The model's tool call could not be parsed (retry also failed).
Retrying did not fix it, and even after resetting the conversation with /clear, the same error would come back after continuing to work for a while. In this article, we share the cause we identified by analyzing the actual session log (jsonl), together with countermeasures.
To state the conclusion up front: this was caused neither by user-side misconfiguration nor by context exhaustion, but by
a streaming bug on the model-response side that occurs with the combination of Opus 4.7 (1M context) + extended thinking
.
Symptoms
The environment in which the error occurred is as follows.
- Claude Code 2.1.148
- Model: Opus 4.7 (1M context)
- Plan: Claude Max
- Session state: Messages 371.7k / 1M tokens (about 37% used, 58.5% free)
- MCP servers: only chrome-devtools connected (2.3k tokens)
- CLAUDE.md: 22.7k tokens
- auto-compact had not triggered
The error was not tied to any particular tool call — it occurred right after Bash, Edit, and MCP (chrome-devtools) calls alike. Retries returned the same error, ultimately halting with "retry also failed."
At first we suspected the conversation might be too long, or the MCP tools might have ballooned, but /context showed 58.5% free capacity, so those hypotheses do not hold.
The precise cause, found in the session log
The decisive clue was in the jsonl file where Claude Code stores the session.
The storage location differs by OS.
Windows
%USERPROFILE%\.claude\projects\<project-name>\<session-id>.jsonlmacOS / Linux
~/.claude/projects/<project-name>/<session-id>.jsonl<project-name> part is the working directory path converted using separator characters (for example, C--Users-foo-projects-myapp) — a name in which drive letters and slashes have been replaced with -).ls or dir on that directory will show your recently used sessions lined up by file name.
Opening this file and examining the assistant message immediately preceding the parse error, we found the following structure.
Opening this file and examining the assistant message immediately preceding the parse error, we found the following structure.
{
"message": {
"model": "claude-opus-4-7",
"role": "assistant",
"content": [
{
"type": "thinking",
"thinking": "",
"signature": "..."
}
],
"stop_reason": "tool_use",
"stop_sequence": null
}
}
Three anomalies are occurring here simultaneously.
1. The content array contains nothing but a single thinking block
Normally, thinking should be followed by text blocks or tool_use blocks. This response, however, contains nothing but thinking.
2. The thinking content is an empty string
"thinking": "" — the reasoning content itself is empty.signature field is present and correct, so as far as the Anthropic API server is concerned, a thinking block was generated — yet its content is empty.
3. stop_reason is tool_use yet no tool_use block exists
This is the most fatal of the three.stop_reason: "tool_use" is the signal that the model stopped in order to call a tool, but the crucial tool_use block is missing from content.
Claude Code's parser processes responses on the premise that "if stop_reason is tool_use, there must be a tool_use block in content." Because that block does not actually exist, the result is the The model's tool call could not be parsed error, and since retries return the same broken response, it ends in retry also failed.
In other words, this is not a bug in the Claude Code client — the streaming response returned by the Anthropic API (the model) is itself malformed.
Related official Anthropic issues
This pattern is almost identical to the phenomenon reported in the anthropics/claude-code repository, in Issue #24662. That issue reports cases where empty text/thinking blocks get inserted between thinking blocks during streaming, making it impossible to resend the conversation to the API.
In addition, the Medium article "How I Stopped Getting Stream Idle Timeout Errors in Claude Code" (April 2026) reports that stream-related errors have surged since the release of Opus 4.7, and multiple issues filed since mid-April explicitly name Opus 4.7 and the 1M context variant as triggers. Anthropic is aware of this as well, and the changelog shows a continuing series of fixes around stream handling.
Sorting out the cause
Organizing the observations, the cause comes down to the following combination.
| Factor | Contribution |
|---|---|
| Bug in Opus 4.7's response streaming | Core |
| extended thinking defaults to xhigh (thinking-heavy) | High |
| 1M context variant | Medium |
| Long-running session (cache_read over 390k tokens) | Medium |
What we would especially like to emphasize is that context usage and the number of MCP servers were not the main factors in this case./context showing 58% headroom did not prevent the error — because this is not an input-side capacity problem but a structural bug on the output side (the model's response).
At release, Opus 4.7's default effort is set to xhigh, a design that makes heavy use of thinking blocks. Combined with the 1M context variant, the stream appears prone to breaking when emitting thinking against long inputs.
Countermeasures
Here are the measures that actually proved effective, with their rationale, in order.
1. Lower the effort setting to curb thinking
/effort medium
or low。
Opus 4.7's default is xhigh. The more thinking-heavy the response, the more likely you are to see breakage like this one — an empty thinking block with a stop_reason of tool_use. Lowering effort reduces the dependence on thinking, which is about as close to addressing the root as a workaround gets.
2. Disable the 1M context variant
set CLAUDE_CODE_DISABLE_1M_CONTEXT=1
claude
This environment variable is listed in the official documentation. Multiple GitHub issues report output corruption specific to the 1M context variant, so turning it off eliminates one of the reproduction conditions. You revert to the standard 200k-context Opus 4.7.
3. Discard broken sessions instead of resuming them
The nasty part of this bug is that once a broken assistant message has been written to the jsonl, every restart via --resume or --continue resends that same broken message as part of the history. Claude Code's automatic retries fare no better — if the server returns the same response, the outcome is the same.
exit
claude # do not use resume/continue
If you need continuity of work, snapshot the state into CLAUDE.md or a history file (e.g., history/HANDOVER.md) and resume in a fresh session.
4. Update Claude Code to the latest version
claude update
Versions 2.1.148 → 2.1.150 contain a continuing series of stream-handling fixes. Anthropic officially recognizes this class of bug and ships fixes at a steady pace, so staying as current as possible is advisable.
5. Report it to Anthropic with the /bug command
Since this is a bug in Anthropic's model/streaming, reporting it is the single most valuable countermeasure.
/bug
If you include the session ID and request_id, Anthropic can directly investigate the model response for that request. Because this is not a client configuration issue, what users can do at the root level is limited — ultimately, we have to wait for Anthropic's fix.
Measures that did not work, or barely helped
For completeness, here are the measures we tried first that had little effect.
/clearto reset the conversation history: It stops temporarily, but recurs within a few turns. Since the cause is not the session history but the model response itself, this is not a fundamental fix.- Disconnecting MCP servers: Ours used only 2.3k tokens to begin with, so the contribution was small. It can be effective in environments where MCP has ballooned.
/compact: Pointless here, since context usage was low.
Summary
"The model's tool call could not be parsed (retry also failed)" looks on its face like a failure to parse a tool call, but in reality it is a phenomenon in which the model's response comes back structurally broken.
Inspecting the jsonl, we see:
contentcontains nothing but a thinking block- thinking is an empty string
stop_reason: "tool_use"yet no tool_use block
All three occur together as a set, and from the parser's point of view this is unrecoverable.
The practical countermeasures we were able to identify this time are:
/effort mediumto curb thinkingCLAUDE_CODE_DISABLE_1M_CONTEXT=1to turn off the 1M context- Discard broken sessions instead of resuming them
- Keep Claude Code up to date
/bugto report it to Anthropic
These are the five. If this error occurs frequently despite ample free context, rather than suspecting your own setup first, we recommend taking a look at the jsonl files under Claude Code's session logs (on Windows, %USERPROFILE%\.claude\projects\; on macOS/Linux, ~/.claude/projects/). If the assistant-side responses have turned into empty thinking blocks, you are seeing the same symptom as in this article.
One final note: this class of bug has increased since the release of Opus 4.7, and Anthropic is aware of it and continues to ship fixes.
In the long run, model and CLI updates should resolve it. Until then, the realistic approach is to adjust the effort setting and the handling of 1M context so as to step on the bug as rarely as possible.
Your Claude Code can do more for you.
There is no established "right answer" yet for agent-first development. We have pushed Claude Code hard in our own development work and systematized what works — and where the pitfalls lie.
Our engineers, with decades on the front lines of software engineering, have taken this on in earnest — and we deliver that battle-tested knowledge to you, organized and ready to use.
Explore our Claude Code enablement services →Thank you for reading.
We hope you found this useful.
See you next time!