From 92b32fdf21a4ed882e7e20bad369caddce4b2cb2 Mon Sep 17 00:00:00 2001 From: kumarabhirup Date: Tue, 17 Mar 2026 14:41:46 -0700 Subject: [PATCH] fix(chat): use refs in stop handler to avoid stale closures Reads sessionId and subagentSessionKey from refs instead of state so the stop button works even before React re-renders. --- apps/web/app/api/chat/stop/route.ts | 1 + apps/web/app/components/chat-panel.tsx | 22 ++++++++++++---------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/apps/web/app/api/chat/stop/route.ts b/apps/web/app/api/chat/stop/route.ts index c4886dca8aa..a19327445d6 100644 --- a/apps/web/app/api/chat/stop/route.ts +++ b/apps/web/app/api/chat/stop/route.ts @@ -45,5 +45,6 @@ export async function POST(req: Request) { if (aborted || abortedChildren > 0) { trackServer("chat_stopped"); } + return Response.json({ aborted, abortedChildren }); } diff --git a/apps/web/app/components/chat-panel.tsx b/apps/web/app/components/chat-panel.tsx index 711d9f698be..fff0c343c66 100644 --- a/apps/web/app/components/chat-panel.tsx +++ b/apps/web/app/components/chat-panel.tsx @@ -1849,10 +1849,12 @@ export const ChatPanel = forwardRef( reconnectAbortRef.current?.abort(); setIsReconnecting(false); - // Stop the server-side agent run and wait for confirmation so the - // session is no longer in "running" state before we stop the - // client-side stream (which may trigger queued message flush). - const stopKey = subagentSessionKey || currentSessionId; + // Read from refs to avoid stale closures — sessionIdRef is updated + // synchronously in handleEditorSubmit, so it's always current even + // if React hasn't re-rendered with the new state yet. + const sk = subagentSessionKeyRef.current; + const sid = sessionIdRef.current; + const stopKey = sk || sid; if (stopKey) { try { await fetch("/api/chat/stop", { @@ -1861,17 +1863,17 @@ export const ChatPanel = forwardRef( "Content-Type": "application/json", }, body: JSON.stringify( - subagentSessionKey - ? { sessionKey: subagentSessionKey } - : { sessionId: currentSessionId }, + sk + ? { sessionKey: sk } + : { sessionId: sid }, ), }); } catch { /* ignore */ } } - // Stop the useChat transport stream (transitions status → "ready"). - void stop(); - }, [currentSessionId, subagentSessionKey, stop]); + // Stop the useChat transport stream (transitions status → "ready"). + void stop(); + }, [stop]); // ── Queue handlers ──