Minimal reproduction for a @cloudflare/ai-chat@0.6.2 recovery issue where a browser useAgentChat / AI SDK useChat stream remains stuck after the Durable Object restarts during a response.
- A React client connects to an
AIChatAgentover WebSocket withuseAgentChat. - The agent has
chatRecovery = true. - The first response emits text plus a partial tool input chunk, then waits for 45 seconds.
- If the Worker / Durable Object is restarted during that wait, recovery persists the partial assistant response and schedules a server-side continuation.
- The continuation completes under a new request id.
With upstream @cloudflare/ai-chat@0.6.2, the original local browser stream may never receive done for its original request id, so useChat stays in a streaming state even after the continuation finishes.
cd /path/to/cloudflare-ai-chat-recovery-stuck-stream
npm install
npm run dev:workerIn another terminal:
cd /path/to/cloudflare-ai-chat-recovery-stuck-stream
npm run devOpen the Vite URL, usually http://localhost:5173.
- Click Start slow stream.
- Wait until the page shows Ready for restart.
- While the response is still streaming, restart the Worker process running
npm run dev:worker:
# stop wrangler dev with Ctrl-C, then start it again
npm run dev:worker- Wait for the browser to reconnect and for the server-side continuation to finish.
- Capture the final page state.
The key evidence is the Current Result panel:
- Expected behavior means the recovered continuation arrived and
isStreamingreturned tofalse. - Bug reproduced means the recovered continuation arrived, but
chat.status/isStreamingstill show that the original browser stream is active.
- The browser-side
useAgentChat/useChatstate eventually returns to idle. statusis no longerstreamingorsubmitted.isStreamingbecomesfalse.
- The continuation response is broadcast with
continuation: trueunder a new request id. - The original local
ReadableStreamcreated byWebSocketChatTransport.sendMessagesis never closed for the original request id. - The React client can keep reporting
status: "streaming"/isStreaming: true. - Tool-part diagnostics are included only to make the interrupted assistant response visible; the main assertion is the streaming state.
- This repro uses React 19 to avoid the separate React 18 static import issue from
@cloudflare/ai-chat@0.6.2. - The repro flushes partial stream chunks before the pause so local recovery has persisted assistant state to reconstruct after restart.
- The Worker intentionally uses manual AI SDK UI stream chunks so no model API key is required.