Skip to content

fix(ui): rebuild partialToolCalls on resume for input-streaming tool parts#14255

Open
giulio-leone wants to merge 1 commit intovercel:mainfrom
giulio-leone:fix/resume-partial-static-tool-calls
Open

fix(ui): rebuild partialToolCalls on resume for input-streaming tool parts#14255
giulio-leone wants to merge 1 commit intovercel:mainfrom
giulio-leone:fix/resume-partial-static-tool-calls

Conversation

@giulio-leone
Copy link
Copy Markdown

Summary

Fixes #14027

When createStreamingUIMessageState receives a lastMessage containing tool parts in input-streaming state (e.g. during resumeStream()), the partialToolCalls map was initialized as {}. This caused subsequent tool-input-delta chunks to fail because the lookup for the existing tool call returned undefined, throwing:

Received tool-input-delta for missing tool call with ID "...".
Ensure a "tool-input-start" chunk is sent before any "tool-input-delta" chunks.

Root Cause

createStreamingUIMessageState never reconstructed partialToolCalls from existing input-streaming tool parts in the provided lastMessage. Fresh streams work fine because they always start with tool-input-start, but resumed streams skip that chunk since the tool part already exists in the hydrated message.

Fix

After constructing the message, iterate over any existing tool parts in input-streaming state and pre-populate partialToolCalls with their current state (serialized input text, index, tool name, dynamic flag, title). This enables the stream processor to correctly handle tool-input-delta chunks during resume.

Changes

  • packages/ai/src/ui/process-ui-message-stream.ts — Rebuild partialToolCalls in createStreamingUIMessageState from existing input-streaming tool parts
  • packages/ai/src/ui/process-ui-message-stream.test.ts — Add regression tests for resuming both static and dynamic tool parts in input-streaming state

Tests

96/96 tests pass (vitest run --config vitest.node.config.js src/ui/process-ui-message-stream.test.ts), including 2 new regression tests.

…parts

When createStreamingUIMessageState receives a lastMessage containing
tool parts in input-streaming state, the partialToolCalls map was
initialized as empty. This caused tool-input-delta chunks during
resume to fail because the lookup for the existing tool call returned
undefined.

The fix reconstructs partialToolCalls entries from any existing
input-streaming tool parts in the lastMessage, enabling resumed
streams to continue appending deltas to in-progress tool calls.

Fixes vercel#14027

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@tigent tigent bot added ai/ui anything UI related bug Something isn't working as documented reproduction provided labels Apr 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai/ui anything UI related bug Something isn't working as documented reproduction provided

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Resume of partial static tool calls crashes in createStreamingUIMessageState

1 participant