Failed server tool call is saved without `error`, so it reloads as complete
@tombeckenham is already working on this.
Since Sep 23, 2026.
Assessment
This issue has not been assessed yet.
Description
TanStack AI version
@tanstack/ai 0.58.0. Also 0.55.0. The code is the same on main.
Framework/Library version
Framework-agnostic (Node 24)
Describe the bug and the steps to reproduce it
A server tool call fails when the handler throws, when the input fails its schema, or when the tool does not exist. chat() streams the TOOL_CALL_RESULT with metadata.tanstack.state: 'output-error'. The client then shows a tool-result part with state: 'error' and error, as the client tools docs describe.
But the tool message that chat() adds to its message history has no error:
{ role: 'tool', content: '{"error":"lookup is down"}', toolCallId: 'call_1' }
Middleware reads that history in onFinish, and @tanstack/ai-persistence saves it. On a reload, modelMessagesToUIMessages gives the tool-result part state: 'error' only when msg.error is set (messages.ts#L1128-L1141). As a result, the part comes back with state: 'complete' and no error. The UI shows the call as failed while the run streams, and as successful after a reload.
buildToolResultChunks uses result.state to tag the chunk, but not to build the message (index.ts#L3157-L3185).
Steps:
- In the linked repo, run
npm install && npm run repro. No API key is necessary. A scripted adapter makes the tool call. - For each of the three failures, the script prints the streamed metadata, the saved tool message, and the rebuilt
tool-resultpart. This is the output for the handler that throws:
## handler throws
1. streamed TOOL_CALL_RESULT metadata: { tanstack: { state: 'output-error' } }
2. saved tool message: {
role: 'tool',
content: '{"error":"lookup is down"}',
toolCallId: 'call_1'
}
3. rebuilt tool-result part: { state: 'complete', error: undefined }
Expected: the saved tool message has error, and the rebuilt part is { state: 'error', error: 'lookup is down' }. That is the same state that the stream processor sets live (processor.ts#L1655-L1682).
When result.state === 'output-error', set error on that message. This fixes all three cases in the repro. A PR follows.
Related: #1386 and #1401 are about denied and cancelled calls. #1401 adds toolResultOutcome to their metadata. It does not mark a plain failure. I ran a test of the three cases against the head of #1401, and all three still rebuild as complete. Both change the same block of code.
Your Minimal, Reproducible Example - (Sandbox Highly Recommended)
https://github.com/aayushbtw/tanstack-ai-tool-error-repro
Do you intend to try to help solve this bug with your own PR?
Yes, I am also opening a PR that solves the problem along side this issue
Terms & Code of Conduct
- I agree to follow this project's Code of Conduct
- I understand that if my bug cannot be reliable reproduced in a debuggable environment, it will probably not be fixed and this issue may even be closed.
- Dominant language
- TypeScript
- Stars
- 3.1k
- Forks
- 331
- Avg merge
- 1d 10h
- Merged PRs (30d)
- 130
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from TanStack/ai
-
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
-
waiting-on: maintainer
-
waiting-on: maintainer
-
has-pr waiting-on: maintainer
Difficulty 3/5 1-2 days Newbie friendliness 70/100
-
waiting-on: maintainer
Similar issues
-
bug(cli): hapi doctor inline-media prints a fabricated B:\ helper-script path in packaged installs Open
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
-
Crush Open
Difficulty 1/5 Under an hour Newbie friendliness 85/100
catppuccin/catppuccin#3125 ·
-
Add a SECURITY.md Open
Difficulty 1/5 Under an hour Newbie friendliness 90/100
ElementsProject/cln-application#167 · 1 comment · 1 reaction ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
Quantco/pnpm-licenses#17 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 75/100