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_response streaming
- a replay derived from a real production failing stream
Reproduction
Repo:
Run:
Open:
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:
6 query_history tool calls
91 tool-input-delta chunks
6 tool-input-start
6 tool-input-available
6 tool-output-available
- fixed
8x replay speed
Why this appears to happen
useAgentChat() installs WebSocketChatTransport, and that transport currently forwards each parsed chunk immediately with controller.enqueue(chunk):
Downstream, every tool-input-delta chunk reparses partial JSON and immediately writes a new assistant message snapshot:
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-delta chunks before calling controller.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-delta bursts
- 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:
That looks like a workaround, not the root fix.
Summary
useAgentChatcan enterstatus: "error"with:I have a standalone repro that uses:
AIChatAgentuseAgentChatcf_agent_use_chat_responsestreamingReproduction
Repo:
9fddb989d95b2d330d5c6da44b13e858bb3351c9Run:
Open:
The page auto-sends one message and replays a captured multi-tool stream through a real
AIChatAgent+useAgentChatpath.Actual result
The page ends in
Status: errorand renders:The console stack points into the chat-store update path and includes:
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-available8xreplay speedWhy this appears to happen
useAgentChat()installsWebSocketChatTransport, and that transport currently forwards each parsed chunk immediately withcontroller.enqueue(chunk):Downstream, every
tool-input-deltachunk reparses partial JSON and immediately writes a new assistant message snapshot:So the failure looks like:
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 reachuseChat().Possible fix directions
Most promising first fix in
cloudflare/agents:tool-input-deltachunks before callingcontroller.enqueue(chunk)Other possible fixes:
useChat()once per microtask / frametool-input-deltaburstsExisting mitigation
useChat()already supportsexperimental_throttle, anduseAgentChat()inherits that option throughUseChatParamsforwarding:That looks like a workaround, not the root fix.