Skip to content

Conversation

cdalton713
Copy link

Adds a null check to prevent errors when processing a reasoning-end message for a non-existent or already removed reasoning part.

Summary

Getting runtime errors when two reasoning end events come in from OpenAI.

Manual Verification

Added validation that the reasoning event exists.

Adds a null check to prevent errors when processing a reasoning-end message for a non-existent or already removed reasoning part.
reasoningPart.state = 'done';
delete state.activeReasoningParts[chunk.id];

if (reasoningPart){
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reasoning-delta case has the same issue that was just fixed in reasoning-end - it doesn't check if the reasoning part exists before accessing its properties.

View Details
📝 Patch Details
diff --git a/packages/ai/src/ui/process-ui-message-stream.ts b/packages/ai/src/ui/process-ui-message-stream.ts
index e2198e158..6620091dd 100644
--- a/packages/ai/src/ui/process-ui-message-stream.ts
+++ b/packages/ai/src/ui/process-ui-message-stream.ts
@@ -346,9 +346,11 @@ export function processUIMessageStream<UI_MESSAGE extends UIMessage>({
 
             case 'reasoning-delta': {
               const reasoningPart = state.activeReasoningParts[chunk.id];
-              reasoningPart.text += chunk.delta;
-              reasoningPart.providerMetadata =
-                chunk.providerMetadata ?? reasoningPart.providerMetadata;
+              if (reasoningPart) {
+                reasoningPart.text += chunk.delta;
+                reasoningPart.providerMetadata =
+                  chunk.providerMetadata ?? reasoningPart.providerMetadata;
+              }
               write();
               break;
             }

Analysis

Null check missing in reasoning-delta handler can cause TypeError

What fails: processUIMessageStream() in reasoning-delta case accesses reasoningPart.text without null check, causing TypeError when reasoning part doesn't exist

How to reproduce:

// Simulate finish-step clearing activeReasoningParts, then reasoning-delta arriving
const state = { activeReasoningParts: {} };
const chunk = { id: "test-id", delta: "more text" };
const reasoningPart = state.activeReasoningParts[chunk.id]; // undefined
reasoningPart.text += chunk.delta; // TypeError: Cannot read properties of undefined (reading 'text')

Result: TypeError: Cannot read properties of undefined (reading 'text')

Expected: Should gracefully handle missing reasoning parts like reasoning-end case does with if (reasoningPart) null check

The finish-step case resets state.activeReasoningParts = {} which can cause this scenario when delta messages arrive after step completion.

@gr2m
Copy link
Collaborator

gr2m commented Sep 15, 2025

can you please share a full example where the error occurs, so we can test your fix? If we go ahead, this PR will need a test, and a changeset

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants