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.
// Server-side code that may experience assistant message duplication on the clientexport 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.
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 }); }, }), });}