快速结论:在 Canary 版本桌面端点击侧边栏群组会话时,页面会短暂进入群组路由然后又静默跳回之前的智能体/话题页。优先怀疑 ChatHydration 的主题订阅与 GroupIdSync 卸载清理之间存在竞态条件。
适用环境:LobeChat Desktop Canary 渠道,版本 2.2.14-canary.80 / 2.2.14-canary.81(两个版本均可复现);macOS arm64 + Electron。Issue 中并未确认 Web 端是否可复现。
最快修复方案:暂无确认的一步修复方案。该问题在 Issue 关闭时仍处于根因分析阶段,官方尚未合并针对此竞态的修复 PR。
注意事项:下方解决步骤为基于 Issue 讨论的推断方案,属于“可优先尝试”范畴,未经官方验证,请先在 Canary 测试环境中验证效果。
问题场景
在 LobeChat Canary 桌面版中,点击侧边栏任意群组会话(路由形如 app://renderer/group/cg_...)时,地址栏会短暂切换到群组页面,随后 UI 静默跳回之前的智能体/话题页,群组会话完全无法使用。通过 Chromium DevTools Protocol 探测确认:路由切换本身成功(readyState: complete),没有崩溃、没有错误边界渲染、也没有任何控制台报错,跳转过程完全静默。
报错原文
Group chat opens then silently bounces back to previous page (ChatHydration × GroupIdSync race, Canary)
11:30:04 → app://renderer/group/cg_OeHhR8d7wrwX (clicked group A — route OK, readyState complete)
11:30:24 → app://renderer/group/cg_gd2LdhiuIH6m (clicked group B — route OK, readyState complete)
11:31:00 → app://renderer/agent/agt_.../tpc_... (bounced BACK to the original agent topic page)
Persistent: ResizeObserver loop completed with undelivered notifications
On topic open: TRPCClientError: No running operation found on this topic
原因分析
Issue 中的主要假设是一个竞态条件:ChatHydration 和 GroupIdSync 的卸载清理互相竞争,可能原因如下——
点击群组 B 后路由切换成功,ChatHydration 挂载并订阅 useChatStore.activeTopicId;GroupIdSync 在切换群组时调用 switchTopic(null) 并将 activeTopicId 置为 null。问题出在 GroupIdSync 的 unmount 清理上:它会在卸载时执行 useAgentGroupStore.setState({ activeGroupId: undefined })。如果旧群组的 unmount 发生在 ChatHydration 订阅新群组 activeTopicId 之后,useGroupContext 会读到 currentGroup = undefined,导致 groupId = null、agentId = '',整个会话上下文在首次渲染时为空。ChatHydration 内部基于过期的上下文调用 navigate(nextUrl, { replace: true }),从而把用户弹回原页面。
另外,Issue 明确指出:先前修复了 agent 会话中类似竞态的 PR #14231,但群组侧一直没有做同等保护;现有 PR #16149 只修复了数据持久化路径,未保护 ChatHydration 的导航路径。
环境排查
- Desktop 版本:
2.2.14-canary.80或2.2.14-canary.81;更早的2.2.14-canary.74也有崩溃表现(见 #18210)。 - 操作系统:macOS arm64,Electron 环境。
- 确认是否为 Desktop 特有:竞态位于渲染进程(React/Zustand/react-router),Web 客户端理论上也可能触发,但 Electron 单持久 webview 的组件卸载时序更容易复现;若条件允许,可在 Web 端快速连续点击群组尝试复现。
- 可借由 CDP 探测确认路由状态:
--remote-debugging-port=9222+--enable-logging。
解决步骤
- 确认问题可稳定复现后,先检查 zustand 状态发散:在跳转窗口期间分别检查
chatStore.activeGroupId与agentGroupStore.activeGroupId。如果两个值不一致(一个为新群组 ID、另一个为 undefined),则基本坐实 unmount 竞态。 - 可优先尝试的修复方向一:修改
GroupIdSync.tsx的useUnmount清理逻辑,增加守卫条件——只有在“新群组的GroupIdSync尚未挂载”时才清除 store 状态,避免旧群组卸载时误清新群组的上下文。 - 可优先尝试的修复方向二:在
ChatHydration调用navigate之前增加防御性校验——确认gid非空且与agentGroupStore.activeGroupId一致,不匹配则放弃导航,避免用过期上下文触发错误跳转。 - 参考此前 agent 会话的修复先例 PR #14231(清除 agent 切换时的陈旧 topic),在群组场景做同等处理——旧群组卸载时清除陈旧的 activeTopicId。
- 修改后请在 Canary 构建中回归验证:快速点击多个不同群组,确认不再弹回原页面。
验证方法
修复后重复 Issue 中的复现步骤:在侧边栏连续点击多个群组,观察浏览器地址是否稳定停留在 app://renderer/group/cg_...,不再弹回之前的 agent/.../topic/... 页面。同时用 CDP 探测确认 location.href 在点击后不再发生回跳;也可以检查两个 zustand store 的 activeGroupId 是否保持一致。
参考来源
这个方案解决了吗?
可以继续搜索完整报错,或查看同一工具的其他排查指南。


