TokenPad

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.

The message you are seeing

Anthropic
tool_use ids were found without tool_result blocks immediately after: toolu_xxx. Each tool_use block must have a corresponding tool_result block in the next message.
OpenAI
An assistant message with 'tool_calls' must be followed by tool messages responding to each 'tool_call_id'.

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. 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. 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. 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. 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

  1. 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.

  2. 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.

  3. 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.
  4. 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

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.