The model's tool call could not be parsed (retry also failed)
The API call worked. A response came back, tokens were generated and billed, and
then your client failed to turn part of that response into a callable tool
invocation. That rules out most of what people check first: this is not a
rejected request (those come back as a 400 before any model runs), not your
API key, not a quota, not capacity, and not the tool itself failing — the tool
never ran. It is a failure in the narrow gap between the model emitting a call
and the client executing it. And the parenthetical is not a footnote; it is the
whole diagnosis.
Data as of 2026-09. Vendor limits and defaults change; check the official docs for current values before acting on any number below.
What “retry also failed” is actually reporting
A single malformed tool call is unremarkable. Sampling is stochastic, a call is structured output, and structured output occasionally comes out wrong. That is precisely why clients handle it silently: the first bad call never reaches you, because the client asks again before showing you anything.
So by the time this string appears, two independent samples have already failed on inputs that were nearly identical. That is the interesting fact, and it inverts the reading. The question is no longer “why did the model make a mistake” — it is “what did both attempts have in common?” Two draws from the same distribution coming out broken says the distribution is skewed, not that you got unlucky twice.
Four things stayed constant across both attempts: the tool definitions you sent, the conversation prefix, the output-length ceiling, and the transport. One of those four is the cause. Everything below is about deciding which.
Is retrying useful?
No — you would be running attempt three of something that already failed twice, against inputs you have not changed.
The retry this message names already happened, automatically, inside your client. Pressing Enter again does not add a new mechanism; it adds a third sample from a distribution that has now produced two failures out of two. If a tool call in this session is going to parse, it usually parses on the first attempt.
Retrying is also not free. A failed turn still consumed input tokens for the whole conversation and output tokens for the broken call, and in a long session that is the expensive half of the request. Three attempts is three full replays of your history.
There is a separate retry budget that people reach for here and it is the wrong knob. A client’s automatic retries for transient failures — in Claude Code, up to 10 attempts with exponential backoff by default — cover connection errors, rate limits and 5xx responses. This is none of those. The response arrived intact and was rejected locally, so no amount of raising that number touches it.
The one case where re-running is reasonable: you change something first. Change one variable, run once, and read the result as evidence about that variable.
Telling the four constants apart
Each of these has a test you can run in under a minute, and the tests are ordered by how cheap they are.
- Always the same tool. The clearest signal in the list. If every failure names one tool and other tools work all day, the constant is that tool’s schema. Deeply nested object parameters, very large enums, and free-form string parameters that are expected to carry code or JSON are all overrepresented here — a parameter whose value is itself quoted, escaped content is the format most likely to come back subtly malformed.
- Always the same kind of call, across tools. File writes, patches, long shell commands — anything whose arguments are large. That pattern points at the output ceiling rather than the schema: the call began correctly and the response stopped before the arguments closed. A truncated call is syntactically indistinguishable from an invented one once it reaches the parser.
- Only late in long sessions, never at the start. The constant is the conversation prefix. Look for what is in the history that was not there an hour ago — usually a tool result containing raw JSON or a partial function call that the model is now pattern-matching against.
- Random tools, random sizes, and other stream-shaped failures nearby. The constant is the transport. A tool call assembled from a stream that broke mid-block arrives as a fragment. The tell is that the session also shows connection or stream errors around the same time; if it does, fix that first and this goes away as a side effect.
Fix by which constant you found
- One tool’s schema — flatten it. Replace a nested object parameter with
two or three flat ones, cut an enum down to the values you actually use, and
take any JSON example out of the parameter
description: an example of the format inside the description competes with the format the client expects at the top level. If the tool is one you wrote against MCP, this is your fix and it is a code change, not a setting. - Truncated arguments — raise the output ceiling for the request. This is
the fix people refuse for the wrong reason, believing a high ceiling costs
them rate limit. On the Claude API it does not: output tokens count toward the
per-minute limit as they are actually produced, and
max_tokensdoes not factor into that accounting, so a ceiling you never reach carries no penalty. Separately, stop asking for enormous arguments in one call — a patch split across three edits is three calls that each parse. - A poisoned conversation prefix — start a new session for the task rather than clearing and continuing, and keep large raw payloads out of the context by having tools return summaries and paths instead of whole documents.
- The transport — this one is not really about tool calls at all, and the advice lives with the stream failures. Fix the connection path and re-test.
What the failed turn left behind
Worth checking before you do anything else, because it decides whether your next message even gets a chance to work.
A tool call that could not be parsed produced no tool execution and therefore no
result. Depending on how your client wrote that turn to disk, the stored history
may now contain an assistant message holding a tool_use block with nothing
answering it. That state is not self-healing: every subsequent request replays
the same array, and the API rejects it with
a 400 naming tool use concurrency and pointing at /rewind,
or with
the validator’s own wording about a missing tool_result block.
So: if your next perfectly ordinary message also fails, you have two problems stacked, and the second one is the one to fix first. Most clients avoid this by never writing an unparseable call into history at all — but “most” is not “all”, and one plain message is a cheap way to find out which kind you have.
Confirming it is actually fixed
One successful call proves nothing here. The failure rate you are fighting is somewhere between “always” and “often”, and a single pass is inside the noise of either.
Run the same tool, with arguments of the same size, three times in a row, in a session at roughly the same length as the one that broke. Three clean passes is the confirmation. If you changed the schema, also confirm nothing else broke: a flattened parameter list is a different contract, and a tool that now parses but receives the wrong arguments is a worse failure than this one because it fails silently.
For the truncation case there is a stronger test. Re-run the call that failed with the largest arguments you actually need, and check that the response ended because the model finished rather than because it hit the ceiling. A call that completes for the wrong reason is a call that will fail again at the next size up.
Related errors
If a call in the same batch failed and the others came back with a sibling-tool-call placeholder, that placeholder is bookkeeping rather than a diagnosis — and the tool it is attached to may have executed anyway, which matters before you re-run anything with side effects. If your harness is reporting the opposite problem — the model answered in prose when a tool call was required and none arrived — that is an expectation enforced by your client, not a malformed call, and it has different causes. The AI coding error triage tool sorts this family by the one question that decides your next move: whether the stored history is still valid, or whether only this turn was lost.