59 lines
2.5 KiB
Markdown
59 lines
2.5 KiB
Markdown
# UI 故障说明:Maximum update depth exceeded
|
|
|
|
**适用版本:** 0.1.8
|
|
**状态:** 已修复
|
|
|
|
## 现象
|
|
|
|
在对话运行过程中,浏览器控制台可能出现以下 React 错误:
|
|
|
|
```text
|
|
Maximum update depth exceeded
|
|
```
|
|
|
|
调用栈通常会经过 LangGraph SDK 的
|
|
`StreamManager.notifyListeners()`、`setStreamValues()` 和 React 的
|
|
`forceStoreRerender()`。发生错误后,页面可能停止更新,或者只能在刷新
|
|
线程后看到本轮完整回答。
|
|
|
|
## 根因
|
|
|
|
LangGraph SDK 的流对象使用外部状态存储。以下读取会启用高频订阅:
|
|
|
|
- 读取 `stream.messages` 会订阅 `messages-tuple`。
|
|
- 读取 `stream.values` 会隐式订阅 `values`。
|
|
- 读取 `stream.getMessagesMetadata()` 同样会建立相关消息状态读取。
|
|
|
|
流式响应中的每个消息块或状态快照都会调用
|
|
`StreamManager.setStreamValues()` 并同步通知 React。组件在通知期间继续
|
|
读取流状态、向子组件透传流对象,或在流式回调中额外更新 React 状态时,会
|
|
造成连续嵌套的外部 Store 更新。更新深度超过 React 限制后,即触发
|
|
`Maximum update depth exceeded`。
|
|
|
|
## 修复方案
|
|
|
|
- 不再读取或向子组件传递 `stream.messages`、`stream.values`、
|
|
`stream.getMessagesMetadata()`。
|
|
- 提交请求时仅使用 `streamMode: ["updates"]`,避免请求高频
|
|
`values` 或 `messages-tuple` 流。
|
|
- 提交后先在本地追加用户消息,用于乐观显示。
|
|
- 当对话完成,或运行进入审批中断状态时,通过
|
|
`client.threads.get()` 和 `client.threads.getState()` 读取服务端已
|
|
持久化的 thread record,并刷新消息、待办、文件和中断状态。
|
|
- 对 Context 使用稳定的空数组和空对象常量,避免每次渲染产生新引用。
|
|
- 移除流式回调中额外的 React 状态更新,以及工具组件对 SDK stream 对象的
|
|
透传。
|
|
|
|
## 修复后的显示行为
|
|
|
|
运行期间,UI 保留已发送的用户消息和加载状态。服务端完成该轮对话或暂停等待
|
|
审批后,前端再刷新完整的持久化结果。因此,回答不会逐 token 显示,但可避免
|
|
高频外部状态通知造成的嵌套更新循环,并确保消息、待办、文件与审批状态来自
|
|
同一份服务端持久化数据。
|
|
|
|
## 验证结论
|
|
|
|
- 对话运行期间不再触发 React 的最大更新深度错误。
|
|
- 完成或审批中断后,完整对话及关联状态可正常刷新。
|
|
- 不再对 LangGraph SDK 建立 `values` 或 `messages-tuple` 高风险订阅。
|