bug(desktop): Auto 审批下同批并行 tool_use 竞态——先发的调用未被执行,挂满 600s 兜底报 "timeout"(claude-code,v0.1.57)
- Dominant language
- TypeScript
- Stars
- 2.7k
- Forks
- 401
- Avg merge
- 21h 48m
- Merged PRs (30d)
- 776
Description
**提交人**: 大佬
**客户端版本**: 0.1.57
---
## 现象
Claude Code 会话(权限模式 = 自动审批 Auto)中,Agent 在同一批里并行发出 2 个 tool_use 时,**先发出的那个高概率未被执行**:UI 一直显示进行中,恰好 600.0 秒后该 tool_use 收到内容为字符串 `timeout` 的 tool_result(is_error=true),Agent 才继续。同批后发的调用始终正常秒级返回。
同一会话内 1 小时内复现 4 次,**4 次挂死的全部是同批中先发出的 tool_use**;期间所有单发(非并行)调用无一挂死。
## 环境
- Cindy desktop v0.1.57(macOS,Darwin 25.5.0)
- agent: claude-code 2.1.219,模型 claude-fable-5
- 权限模式:自动审批(Auto)
- 会话工作目录为一个 iCloud 下的目录;挂死与正常的调用均包含工作目录外路径(`~/.claude/`、`~/.codex/` 下的配置/技能文件),故「目录外路径」疑似只是触发审批的前提,竞态发生在并发审批处理
## 复现时间线(同一会话,当地时间,已泛化)
1. 14:30:48 并行 2×Bash(递归 grep 配置目录 / grep 两个 md)→ 后发 25s 返回;**先发 600.0s 后报 `timeout`**
2. 14:43:50 并行 2×Bash(ls 8 个小目录 / grep 3 个 md)→ 后发 6s 返回;先发挂死。期间 App 于 14:54 退出重启,会话被 `[UI_ACTION_TRIGGER]`(app exited mid-run)恢复;该挂死调用仍在整 600.0s 时刻落 `timeout`
3. 14:54:38(恢复后)并行 2×Bash(grep,**显式 timeout:30000** / find)→ 后发 3s 返回;**先发无视 30s 参数,600.0s 报 `timeout`**
4. 15:04:56 并行 2×Read(两个 1.3KB 的 md 文件)→ 后发 6s 返回;**先发 600.0s 报 `timeout`**
## 关键证据(判断「未执行」而非「执行慢」)
- 挂死的命令原样重跑均为毫秒级(递归 grep 0.007s;Read 目标仅 1.3KB);目标目录共 420 个文件,无 FIFO 等特殊文件
- 挂死的 Bash 调用中,一个显式带 `timeout:30000`,另一些适用默认 120s 命令超时——**若命令真正开始执行,应在 30s/120s 报命令超时**;实际全部等满 600.0s,说明命令从未开始执行
- engine 侧会话 jsonl 中,4 个挂死 tool_use 的 tool_result 均为裸字符串 `timeout`(is_error=true),无任何执行输出;同批另一 tool_use 有正常完整结果
- 600s 与 `apps/desktop/src/main/maker-ipc/register.ts` 的 `PERMISSION_INTERACTION_TIMEOUT_MS = 10*60*1000` 一致,符合 `interactionRouter` 超时 fail-closed 路径
- 重启 App 不能消除:重启后同一会话继续复现(第 3、4 次)
## 期望行为
Auto 模式下同批并行 tool_use 的审批应全部被处理并放行/拒绝;若审批请求投递或应答丢失,应快速返回结构化系统错误,而不是静默挂满 600s 并以裸 `timeout` 收场。
## 初步定位怀疑
症状指向并发审批请求的 resolver 登记/应答路由竞态:两个审批请求几乎同时(间隔 <100ms)产生时,先发请求的应答被后发请求顶掉或未命中 resolver。与 #2728 已修复的「先广播、后登记 resolver 导致快速响应被丢弃」竞态同族,但该修复针对 Codex fileChangeApproval 路径;本例发生在 claude-code + Auto reviewer 路径(Bash/Read 均中招)。可能与 #2851(Auto 审阅器故障后审批桥 600s 超时)、#2677(subagent 读工作目录外文件挂 600s)同根。
## 已尝试
- 重启 App:无效,复发
- 让 Agent 改为单发(一次只发一个 tool_use):有效绕过,未再挂死
## 复现建议
Auto 权限模式 + claude-code 会话,让 Agent 在同一 assistant 消息中并行发出 2 个涉及会话工作目录外路径的轻量 tool_use(如两个 Read),观察先发的是否挂至 600s。本例 5 批并行中 4 批中招,复现率高。
---
**OS**: darwin arm64 (25.5.0)
**界面语言**: zh-CN
Contributor guide
Research direction
Start in apps/desktop/src/main/maker-ipc/register.ts and trace the interactionRouter path used by Auto-mode Bash and Read approvals, focusing on resolver registration and response routing for concurrent tool_use requests. Reproduce with two parallel lightweight calls, then verify both complete promptly and that a lost request returns a structured error instead of a 600-second bare timeout.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- desktop
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100