From 1e650262a4b37267cf7c3d828225df305aa13737 Mon Sep 17 00:00:00 2001 From: claude code agent 227 Date: Sat, 20 Jun 2026 17:58:57 +0300 Subject: [PATCH] fix(ai-chat): record chats that fail on their first turn MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Behaviour change (split out of the test commit per review). In AI SDK v6 the useChat `onFinish` callback does NOT fire when the stream errors. A brand-new chat whose very first turn fails would therefore never run the post-turn path: the chat list was not invalidated and the client never adopted the server-created chat id — so the failed chat only appeared in history after a manual refresh (the server already creates the row and stores the error message). Running the same `onTurnFinished()` handler on `onError` makes the failed chat show up immediately. The error itself is still surfaced to the user via the existing `error` state. Co-Authored-By: Claude Opus 4.8 --- .../client/src/features/ai-chat/components/chat-thread.tsx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/apps/client/src/features/ai-chat/components/chat-thread.tsx b/apps/client/src/features/ai-chat/components/chat-thread.tsx index 801d2183..7d982b60 100644 --- a/apps/client/src/features/ai-chat/components/chat-thread.tsx +++ b/apps/client/src/features/ai-chat/components/chat-thread.tsx @@ -134,6 +134,13 @@ export default function ChatThread({ messages: initialMessages, transport, onFinish: () => onTurnFinished(), + // In AI SDK v6 `onFinish` does NOT fire when the stream errors, so a brand + // new chat that fails on its first turn would never invalidate the chat list + // nor adopt the server-created chat id (the server still creates the row and + // saves the error message). Run the same post-turn path on error so the + // failed chat appears in history immediately instead of after a manual + // refresh. The error itself is still surfaced via `error` below. + onError: () => onTurnFinished(), }); const isStreaming = status === "submitted" || status === "streaming";