Repository navigation
useAgentChat can throw "Maximum update depth exceeded" during dense streamed tool-input-delta bursts #1361
Description
Summary
useAgentChat can enter status: "error" with:
Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate.
I have a standalone repro that uses:
- real
AIChatAgent - real
useAgentChat - normal
cf_agent_use_chat_responsestreaming - a replay derived from a real production failing stream
Reproduction
Repo:
Run:
pnpm install
pnpm devOpen:
http://127.0.0.1:43110/
The page auto-sends one message and replays a captured multi-tool stream through a real AIChatAgent + useAgentChat path.
Actual result
The page ends in Status: error and renders:
Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate.
The console stack points into the chat-store update path and includes:
ReactChatState.replaceMessage -> callbacks -> forceStoreRerender
Expected result
The streamed assistant response should complete without entering an error state.
Replay shape
The default replay in the repro repo uses:
6query_historytool calls91tool-input-deltachunks6tool-input-start6tool-input-available6tool-output-available- fixed
8xreplay speed
Why this appears to happen
useAgentChat() installs WebSocketChatTransport, and that transport currently forwards each parsed chunk immediately with controller.enqueue(chunk):
- normal send: packages/ai-chat/src/ws-chat-transport.ts#L241-L245
- tool continuation: packages/ai-chat/src/ws-chat-transport.ts#L526-L529
- resumed stream: packages/ai-chat/src/ws-chat-transport.ts#L607-L611
Downstream, every tool-input-delta chunk reparses partial JSON and immediately writes a new assistant message snapshot:
- partial JSON parse + immediate write: packages/ai/src/ui/process-ui-message-stream.ts#L564-L600
- assistant message replacement: packages/ai/src/ui/chat.ts#L687-L708
- synchronous subscriber fanout: packages/react/src/chat.react.ts#L56-L97
So the failure looks like:
dense chunk burst -> per-chunk assistant message replacement -> synchronous external-store rerender storm
Why I am filing this here
The failing public API is useAgentChat, and the most obvious mitigation point appears to be Cloudflare's websocket transport boundary before chunks reach useChat().
Possible fix directions
Most promising first fix in cloudflare/agents:
- coalesce consecutive
tool-input-deltachunks before callingcontroller.enqueue(chunk)
Other possible fixes:
- buffer parsed chunks and flush them to
useChat()once per microtask / frame - reduce React-visible publish frequency during dense
tool-input-deltabursts - preserve full chunk fidelity internally, but avoid turning every delta into its own render boundary
Existing mitigation
useChat() already supports experimental_throttle, and useAgentChat() inherits that option through UseChatParams forwarding:
- packages/react/src/use-chat.ts#L42-L50
- packages/ai-chat/src/react.tsx#L366-L370
- packages/ai-chat/src/react.tsx#L820-L829
That looks like a workaround, not the root fix.
Activity
threepointone commentedon Apr 23, 2026
unfortunately, this is an ai sdk problem, and experimental_throttle is the recommended way to fix it. is it a problem for you to use it?
threepointone commentedon Apr 24, 2026
I can actually reproduce this, happening more often than usual, looking into it.
fix(mobile/chat): stop AI SDK render storm crashing long chats
threepointone commentedon May 22, 2026
haven't seen this in a while, I think it's fixed, please open a new issue if you see anything.
C2: throttle chat store writes so streaming stops tripping React's up…