LLM API error · 400
Tool result does not match tool use
Every tool call must be answered by a result with a matching identifier, in the right message role. The rules, and the three ways people break them.
What it means
The conversation you sent has a tool call with no matching result, results in the wrong position, or identifiers that do not correspond. The API models the exchange as a strict sequence and rejects anything that breaks it.
This almost always appears while building an agent loop by hand or while constructing a test fixture, not in steady-state operation.
Why it happens
Most likely cause first.
- 1
Mismatched identifiers
The result carries a different id than the call. The error names neither clearly, which makes it feel more mysterious than it is.
- 2
Results in the wrong message
Anthropic expects results as content blocks in the following user message; OpenAI expects separate messages with a tool role. Porting between them without changing this is the most common source of this error.
- 3
A tool failed and no result was sent
Your handler threw, so nothing was appended. The model’s call is left unanswered. An error result is still a result — send one.
- 4
Parallel calls, partially answered
The model requested three tools and your code answered two. Every call in the block needs a result, not just the ones that succeeded.
How to fix it
Print the identifiers on both sides
List every tool call id in the assistant message and every result id in the following one. The mismatch is usually obvious the moment you see them side by side.
Always send a result, including for failures
Wrap your tool handler so an exception produces a result containing the error text. The model handles "that failed" well and handles silence not at all.
Check the message structure for your provider
The two formats are different enough that hand-porting is unreliable. Generate the blocks rather than writing them.
Function Call Message FormatterValid tool_use / tool_result blocks with matching ids, both providers.Answer every call in a parallel block
Iterate over all calls rather than handling the first. Partial answers fail the same way as missing ones.
Stopping it happening again
- Treat the tool loop as a state machine: a call without a result is an invalid state your code should not be able to construct.
- Log the full message array on failure. This error is trivial to diagnose with the array in front of you and painful without it.
- Keep tool results small — they are the largest contributor to a growing agent context, and they are billed on every subsequent iteration.
Tools that help
- Function Call Message FormatterValid tool_use / tool_result blocks with matching ids, both providers.
- AI Agent Configuration BuilderPortable agent config with the one number frameworks never show you: overhead per request.
- Agent Loop Cost SimulatorPer-iteration breakdown showing why agents cost several times the naive estimate.
Frequently asked questions
- Can I skip a tool result if the tool is irrelevant?
- No. Every call needs a result. If the call should not have happened, send a result saying so — that also teaches the model something useful for the next turn.
- How should I report a tool failure to the model?
- As a normal result containing a short, factual error message. Models recover from "the search returned no results" gracefully; they cannot recover from a missing block.