
“The desktop app did not start the remote chat request”——一个被报错文案带偏的排查记
本文部分或全部内容由 AI 辅助撰写。AI 生成的内容可能存在不准确之处,请读者注意甄别。
给 LiveAgent 移动端(agent-mobile,Tauri v2)做聊天功能的时候,撞上一条特别能带节奏的报错:
The desktop app did not start the remote chat request. Please retry.
一开始它只是「偶尔」出现,后来变成「某个场景必现」。为了这一句话,我兜了三个大圈子,最后发现真凶跟这句话里任何一个词都不沾边。这篇把整个排查过程、以及最后怎么破案记录下来。
报错文案是个陷阱
先看这句话的三个误导点:
- 「desktop app」 —— 会让人以为问题是「桌面端没起来」。实际上网关对所有走聊天入口的客户端一视同仁,根本不区分桌面端还是移动端,只是文案写死了 “desktop app”。移动端撞上它,跟「桌面」毫无关系。
- 「did not start」 —— 会让人以为「某件事没被启动」。它确实是个启动超时,但没启动的对象是谁、为什么没启动,这句话一个字都没说。
- 「Please retry」 —— 暗示「重试一下就好」。可如果根因没变,重试一百次也是同一句。
一句话把三个排查方向全带歪了,而我正好全踩了一遍。
三个被带偏的假线索
线索一:agent offline
最早报的是另一个错 “agent offline”。查下来发现移动端把「选中的 agent」持久化在 localStorage 里,而这个 agent 已经离线了(桌面端重启 / 换机 / 多 agent 场景很常见),移动端却一直打向它。
这个是真的 bug,修法是在回放 agent 目录时,只有持久化的 agent 仍「在线」才沿用,否则回落到「在线优先」的自动选择。修完 “agent offline” 确实没了。
但注意——这跟 “did not start” 是两条不同的错误路径:offline 是网关在投递前就拒了(“agent offline”),而 “did not start” 是投递之后 agent 没在时限内确认启动。修了前者,后者依旧。
线索二:OHOS 平台差异
移动端同时在适配 Android 和 HarmonyOS(OpenHarmony)。第一反应是「OHOS 特有的问题」:webview、网络栈、ArkWeb 各种怀疑。
但这个判断很快被证伪——Android 也复现,而且是同一个 APK。同一个二进制、两个平台都出,说明不是平台适配的问题。于是这条也排除了。
线索三:桌面 webview「放了一段时间就不行了」
这是最坑的一条。现象是「同一个 APK,前几天还正常聊天,隔几天再测就出这个错」。我把「放了一段时间」理解成了「桌面端 webview 闲置后被系统节流 / 挂起」:
- 桌面端收到聊天命令后,要由前端主动「claim + mark started」,网关才算这次启动「落定」;
- 我怀疑前端被系统降频后,15s 内没来得及确认,于是撞上启动看门狗;
- 于是搞了一套「轮询等
chat_runtime_ready就绪位 + 超时抛 recovering」的改动。
这套理论说得通、代码也写得有鼻子有眼,但它对这个问题完全不成立——最后全回退了。它错在:我把一个「时间相关的现象」硬套成了一个「代码缺陷」,而没有先验证「到底是什么变量在变」。
破案:换个模型就好了
真正让我回到正轨的,是随手做的一件事——换了个模型:
- 选 deepseek 模型 → 必现 “did not start”;
- 换成 claude → 一切正常;
- 而「两天前的包」配 deepseek 也正常。
到这里才恍然大悟:变量不是平台、不是闲置、不是 agent,是「模型」。前两天的包和现在的包是同一个,代码没变,变的是「deepseek 这个模型这两天在 agent 那一侧失效了」。
为什么「模型失效」会报成「did not start」
这就得看网关那条启动看门狗到底在看什么。命令投递给 agent 之后,网关会等一个「启动落定」信号,内部是两段超时叠加(默认 5s + 10s):
投递命令 → 等 5s → 检查是否"落定" → 再等 10s → 再检查 → 仍没落定 → 判 "did not start"
而「落定」依赖 agent 前端明确回一个 “started”。关键就在这:模型初始化失败,和「agent 根本没启动」,在网关眼里是同一副样子——都是「15s 内没等到 started」。
于是链路就变成:
选 deepseek → 命令里带上 deepseek 的 selected_model → agent 前端拿这份配置初始化这次 run
→ 初始化失败/卡住(key 过期、模型下架、base_url 变了……)
→ 前端始终没回 "started"
→ 15s 看门狗超时 → 笼统地报 "did not start"
报错文案把「模型初始化失败」硬生生翻译成了「桌面端没启动」。真正该出现的错误——「deepseek 的 key 过期了」或「模型不存在」——被看门狗那句通用兜底盖得严严实实。
收获
回头看,这句报错其实是在反复提醒我三件事,只是我一开始没听进去:
- 看门狗报错是「兜底」,不是「根因」。 它只在超时那一刻喊一嗓子,把「agent 挂了」「模型失效」「运行时冷启动」等一堆不同原因压成同一句话。看到它,第一反应应该是「谁没在时限内确认」,而不是照字面去查。
- 别被报错文案锚定。 “desktop app” 只是个没区分客户端的通用词。被文案里的具体名词带着走,是最容易浪费时间的排查姿势。
- 「前几天还能跑、现在不行」+「换个 X 就好了」是配置腐化的典型签名,不是代码回归。 同一个 APK、代码没动、时间变了,第一时间该怀疑的是会过期 / 会漂移的东西:凭据、模型可用性、依赖源……而不是去给代码找 bug。
最后还有一条更值得做的根治:让 agent 把「模型初始化失败」的真实错误透出来,而不是静默超时。这样下次任何模型出问题,用户看到的会是「deepseek:401 鉴权失败」这种能直接定位的报错,而不是一句玄学般的 “did not start”。
如果哪天你也撞上「某个模型一选就报这个、换别的模型就没事」,别急着查网络、查平台、查桌面端——先去看看那个模型的 provider 配置是不是过期了。
非商业转载请注明出处,商业转载请联系作者获得授权。
For non-commercial use, please indicate the source. For commercial use, please contact the author for authorization.
View license