ai
Version:
AI SDK by Vercel - build apps like ChatGPT, Claude, Gemini, and more with a single interface for any model using the Vercel AI Gateway or go direct to OpenAI, Anthropic, Google, or any other model provider.
79 lines (65 loc) • 2.39 kB
text/mdx
title: Repeated assistant messages in useChat
description: Troubleshooting duplicate assistant messages when using useChat with streamText
# Repeated assistant messages in useChat
## Issue
When using `useChat` with `streamText` on the server, the assistant's messages appear duplicated in the UI - showing both the previous message and the new message, or showing the same message multiple times. This can occur when using tool calls or complex message flows.
```tsx
// Server-side code that may experience assistant message duplication on the client
export async function POST(req: Request) {
const { messages } = await req.json();
const result = streamText({
model: 'openai/gpt-5-mini',
messages: await convertToModelMessages(messages),
tools: {
weather: {
description: 'Get the weather for a location',
parameters: z.object({
location: z.string(),
}),
execute: async ({ location }) => {
return { temperature: 72, condition: 'sunny' };
},
},
},
});
return createUIMessageStreamResponse({
stream: toUIMessageStream({ stream: result.stream }),
});
}
```
## Background
The duplication occurs because UI message streams generate new message IDs for each new message.
## Solution
Pass the original messages array to `toUIMessageStream` using the `originalMessages` option. By passing `originalMessages`, the helper can reuse existing message IDs instead of generating new ones, ensuring the client properly updates existing messages rather than creating duplicates.
```tsx
export async function POST(req: Request) {
const { messages } = await req.json();
const result = streamText({
model: 'openai/gpt-5-mini',
messages: await convertToModelMessages(messages),
tools: {
weather: {
description: 'Get the weather for a location',
parameters: z.object({
location: z.string(),
}),
execute: async ({ location }) => {
return { temperature: 72, condition: 'sunny' };
},
},
},
});
return createUIMessageStreamResponse({
stream: toUIMessageStream({
stream: result.stream,
originalMessages: messages, // Pass the original messages here
generateMessageId: generateId,
onEnd: ({ messages }) => {
saveChat({ id, messages });
},
}),
});
}
```