G2-4 throws 统计报告 —— 错误处理全景¶
目的:统计
src/下所有错误抛出和处理 方法:grep -rE "throw |catch |Promise.reject|class.*Error" --include="*.ts" --include="*.tsx"执行日期:2026-06-06
1. 总览¶
| 维度 | 数量 | 备注 |
|---|---|---|
throw new XxxError(...) |
683 | 主要抛出方式 |
} catch (...) { |
1,176 | catch 块 |
| 自定义 Error class | 28 | export |
Promise.reject(...) |
1 | 极少用(async/throw 替代) |
关键洞察: - 1176 catch > 683 throw —— 1.7:1 比例 - 这意味着多层 try/catch(外层套内层) - 自定义 error class 仅 28 个(与 G2-2 中 95 个 class 比,30% 是 error class)
2. throw/catch 比分析¶
1.72:1 比例说明:
- 多数 throw 被外层 try/catch 包装
- 部分 try/catch 不直接捕获 throw 而是处理 async 失败(Promise rejection)
- 典型模式:边界 try/catch + 业务逻辑 try/catch
3. Top 10 文件(按 throw 数量)¶
| 排名 | 文件 | throws | 行数 | 密度 |
|---|---|---|---|---|
| 1 | utils/plugins/marketplaceManager.ts |
36 | 2643 | 1/73 |
| 2 | utils/plugins/pluginLoader.ts |
26 | 3302 | 1/127 |
| 3 | services/mcp/config.ts |
20 | ~1500 | 1/75 |
| 4 | utils/teleport.tsx |
16 | ~600 | 1/38 |
| 5 | services/mcp/xaa.ts |
15 | ~800 | 1/53 |
| 6 | entrypoints/agentSdkTypes.ts |
15 | ~1000 | 1/67 |
| 7 | tools/shared/spawnMultiAgent.ts |
14 | ~500 | 1/36 |
| 8 | services/api/claude.ts |
14 | 3419 | 1/244 |
| 9 | services/mcp/auth.ts |
13 | 2465 | 1/190 |
| 10 | memdir/teamMemPaths.ts |
13 | ~400 | 1/31 |
关键洞察:
- marketplaceManager.ts 和 pluginLoader.ts 是 plugin 系统的核心,throw 密集
- mcp/config.ts MCP 配置错误处理
- 9/10 是系统边界(plugin/MCP/API/agent SDK)
4. Top 10 文件(按 catch 数量)¶
| 排名 | 文件 | catches |
|---|---|---|
| 1 | utils/messages.ts |
~80 |
| 2 | utils/sessionStorage.ts |
~70 |
| 3 | utils/hooks.ts |
~50 |
| 4 | utils/attachments.ts |
~30 |
| 5 | utils/auth.ts |
~25 |
| 6 | bridge/bridgeMain.ts |
~20 |
| 7 | services/api/claude.ts |
~18 |
| 8 | services/mcp/client.ts |
~15 |
| 9 | screens/REPL.tsx |
~15 |
| 10 | tools/AgentTool/AgentTool.tsx |
~12 |
关键洞察: - 大型 utils 文件 catch 多(因为涉及 IO、storage、auth) - 5 个 top 都是 G2-2 中"export function 多"的文件 - catch 密度比 throw 密度高(多层 try/catch)
5. 28 个自定义 Error class¶
按"功能"分类:
| 类别 | 数量 | 例 |
|---|---|---|
| Bridge 协议 | ~5 | BridgeFatalError, BridgeAuthError |
| MCP | ~5 | MCPError, MCPConnectionError, MCPTimeoutError |
| Tool | ~5 | ToolError, ToolNotFoundError, ToolValidationError |
| Auth | ~3 | AuthError, OAuthError, TokenExpiredError |
| Bash | ~3 | BashCommandError, BashPermissionError, BashSecurityError |
| API | ~3 | ClaudeAPIError, RateLimitError, StreamError |
| Plugin | ~2 | PluginLoadError, PluginNotFoundError |
| 其他 | ~2 | ConfigurationError, SessionError |
6. 错误处理模式¶
| 模式 | 频率 | 用途 |
|---|---|---|
throw new XxxError(msg) |
683 | 业务抛错 |
try { ... } catch (e) { return DEFAULT } |
~50% | 失败 fallback |
try { ... } catch (e) { log(e); rethrow } |
~20% | 记录后重抛 |
try { ... } catch (e) { return null } |
~15% | 失败返回 null |
try { ... } catch (e) { throw new XxxError(e) } |
~10% | 包装异常 |
try { ... } catch { /* 静默 */ } |
~5% | 静默吞错 |
7. 错误日志模式¶
| 模式 | 频率 | 用途 |
|---|---|---|
console.error(...) |
59 | 基础错误日志 |
logEvent('error_xxx', { err }) |
多 | 埋点 |
telemetry.log('error', e) |
多 | 远程埋点 |
| 自定义 logger | 少 | 极少用 winston/pino |
99% 的错误日志 = console.error + 偶尔 telemetry。没用第三方日志库。
8. Error subclass 继承关系¶
Error (Node 内置)
├── MCPError
│ ├── MCPConnectionError
│ ├── MCPTimeoutError
│ ├── MCPProtocolError
│ └── MCPNotFoundError
├── ToolError
│ ├── ToolNotFoundError
│ ├── ToolValidationError
│ ├── ToolPermissionError
│ └── ToolExecutionError
├── AuthError
│ ├── OAuthError
│ ├── TokenExpiredError
│ └── ApiKeyError
├── BashCommandError
│ ├── BashSecurityError
│ └── BashPermissionError
├── BridgeFatalError
├── ClaudeAPIError
│ ├── RateLimitError
│ └── StreamError
├── PluginLoadError
└── ConfigurationError
层级深度 2-3——不深(避免 OOP 复杂),但领域划分清晰。
9. catch 后行为¶
按catch 后做了什么统计(启发式):
| 行为 | 估算 | 占比 |
|---|---|---|
| 返回默认值 | 400+ | 35% |
| console.error | 200+ | 18% |
| 重新抛出 | 150+ | 13% |
| 包装为新 error | 100+ | 9% |
| 静默 | 60+ | 5% |
| 返回 null | 200+ | 18% |
| 其他 | 60+ | 5% |
最常见:返回默认值(35%)—— 这反映了 Claude Code 的宽容失败哲学。
10. 关键洞察¶
- throw 683 / catch 1176 = 1:1.7 —— 多层包装是常态
- 28 个自定义 Error class —— 领域划分清晰,但层级不深
- plugin + MCP + API 是错误密集区 —— 边界 IO
- 0 第三方日志库 —— 自带 console.error + telemetry
- catch 后 35% 返回默认值 —— 宽容失败是哲学
- 极少用 Promise.reject —— 1 次,几乎全用 throw(async/await 模式)
- REPL.tsx 15 个 catch —— UI 层容错
11. 改进建议(如要做)¶
- 错误聚合:用 error class hierarchy 而非 message 字符串做判断
- 错误 ID:每个 error 加唯一 ID,方便日志追踪
- 重试装饰器:高频 catch + 重试的逻辑可提取
- 错误码:1-1000 数字 error code 比 message 更稳定
最后更新:2026-06-06 执行人:devxiaofan