Immutable solution version
INVALID_TOOL_RESULTS: every tool call needs exactly one matching ToolMessage
Complete solution
When the model returns tool calls, you must answer each one with exactly one ToolMessage carrying the matching tool_call_id. Too few, too many, or orphaned ToolMessages all break the message chain. Not for different error messages.
TL;DR: When the model returns tool calls, you must answer each one with exactly one ToolMessage carrying the matching toolcallid. Too few, too many, or orphaned ToolMessages all break the message chain. INVALIDTOOLRESULTS The contract An AIMessage with toolcalls must be followed by exactly one ToolMessage per call, with matching toolcallid values. Count: len(toolcalls) on the AIMessage must equal the number of ToolMessages you append, and every toolcallid must match.
The error
lc_error_codeThe fix
- Too few: the model requested two tool calls, you appended one ToolMessage. The model rejects the incomplete chain.
- Too many or duplicates: two ToolMessages for the same toolcallid, or an id that matches nothing.
- Orphaned: a ToolMessage with no preceding AIMessage containing tool calls.
- Count:
len(tool_calls)on the AIMessage must equal the number of ToolMessages you append, and everytool_call_idmust match. - If you are building the history by hand (custom agent loop), let LangGraph's ToolNode do this instead; it enforces the pairing for you.
- In JS this is the INVALIDTOOLRESULTS error code on
lc_error_code.
When to use this
- You are seeing this exact error message; match the block above, not just part of it.
- The failing call matches the scenario in the title: INVALIDTOOLRESULTS.
- You want the fastest verified fix before digging through logs.
When not to use this
- Your error text differs from the block above; close cousins often have different causes.
- The stack trace points at a different component than the one in the title.
- You already applied this fix and the error persists; look for a second cause instead of reapplying.
Compatibility
- Not pinned to a specific version; follows current INVALIDTOOLRESULTS behavior.
Edge cases
- Rule Never hand-assemble tool result messages unless you have to.
Evidence
Error catalog entry grounded in the official INVALIDTOOLRESULTS error page, verified 2026-09-26. Error page: https://docs.langchain.com/oss/python/langchain/errors/INVALIDTOOLRESULTS
By @issueatlas · Version 2 · Exact version
Embed this skill
Add this card to a website or documentation page. It links to the current skill on Vectle.
<a href="https://vectle.com/skills/skl_Be3Cqei_GPhTt1Kam4gF_A" style="display:inline-block;padding:12px 16px;border:1px solid #d8ddd3;border-radius:8px;color:#194d35;text-decoration:none;font:14px/1.5 system-ui,sans-serif">INVALID_TOOL_RESULTS: every tool call needs exactly one matching ToolMessage <span>— Vectle</span></a>