Skip to content

Conversation

Kayrnt
Copy link

@Kayrnt Kayrnt commented Aug 22, 2025

Issue

#8227

Summary

Fixes a bug where parts from previous messages were carried over to subsequent messages when multiple assistant messages arrived in the same HTTP streaming response. This resulted in message contamination where later messages contained both their own parts and parts from earlier messages.

Changes

Core Fix

  • Refactored message creation logic into reusable helper functions:
    • createFreshAssistantMessage(): Creates a fresh assistant message with empty parts array
    • resetActiveStreamingParts(): Resets all active streaming parts to prevent carryover
  • Enhanced start case handling in processUIMessageStream() to detect new messages and reset state appropriately
  • Improved maintainability by eliminating code duplication between message creation scenarios

Test Coverage

  • Added comprehensive test case multiple messages in same HTTP response that reproduces the exact scenario described in the issue
  • Validates that each message contains only its own parts without carryover
  • Ensures proper isolation between messages in the same streaming response

Technical Details

Before (Problematic Behavior)

case 'start': {
  if (chunk.messageId != null) {
    state.message.id = chunk.messageId; // ❌ Only changed ID, kept same parts array
  }
  // ... parts array and active state carried over
}

After (Fixed Behavior)

case 'start': {
  if (chunk.messageId != null && chunk.messageId !== state.message.id) {
    // ✅ Create completely fresh message and reset all state
    state.message = createFreshAssistantMessage<UI_MESSAGE>(chunk.messageId);
    resetActiveStreamingParts(state);
  } else if (chunk.messageId != null) {
    state.message.id = chunk.messageId;
  }
  // ...
}

Example Scenario Fixed

Input Stream:

data: {"type":"start","messageId":"1"}
data: {"type":"text-start","id":"text1"}
data: {"type":"text-delta","id":"text1","delta":"Retrieving the weather!"}
data: {"type":"text-end","id":"text1"}
data: {"type":"data-notification","data":{"agent":"weather", "status": "fetching"}}
data: {"type":"finish"}

data: {"type":"start","messageId":"2"} // ← New message starts here
data: {"type":"text-start","id":"text2"}
data: {"type":"text-delta","id":"text2","delta":"Got the temp!"}
data: {"type":"text-end","id":"text2"}
data: {"type":"data-notification", "data":{"agent":"weather", "status": "ready", "temperature": 100}}
data: {"type":"finish"}

Before (Buggy): Message 2 contained parts from Message 1 + its own parts
After (Fixed): Message 2 contains only its own parts

Please check if the PR fulfills the following requirements:
-->

  • Tests have been added / updated (for bug fixes / features)
  • Documentation has been added / updated (for bug fixes / features)
  • A patch changeset for relevant packages has been added (for bug fixes / features - run pnpm changeset in the project root)
  • Formatting issues have been fixed (run pnpm prettier-fix in the project root)

Related Issues

- Refactor message creation logic into reusable helper functions
- Fix bug where parts from previous messages were carried over to subsequent messages in the same HTTP response
- Add createFreshAssistantMessage() and resetActiveStreamingParts() helpers
- Add comprehensive test case for multiple messages in same response
@lgrammel
Copy link
Collaborator

A single streaming response creates or adds to a single assistant message. Multiple assistant messages in a single stream are not supported by design in AI SDK 5.

@lgrammel lgrammel closed this Aug 25, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants