[ISSUE-0034] TypeError: Failed to fetch 冒到 chrome 扩展错误日志¶
相关源码:
src/utils/ext-context-guard.ts用户反馈:chrome://extensions 错误日志显示 "TypeError: Failed to fetch" + 堆栈追踪指向chunks/ext-context-guard-*.js:48
用户感知¶
用户在 chrome://extensions 详情页"错误"区看到:
直观结论 = 扩展坏了,但实际上业务代码已经 handle 了这些网络错误(如 auth-provider 的 useRequest.onError 回退到"未登录"态)。
根因¶
ext-context-guard.ts:107 v0.10.29 引入的 unhandledrejection listener:
window.addEventListener('unhandledrejection', (e) => {
if (isContextError(e.reason)) trigger();
// ❌ 没 e.preventDefault(),所有 unhandled rejection 都冒泡到 Chrome 错误日志
});
链条: 1. 网络瞬断 → fetch reject "TypeError: Failed to fetch" 2. useRequest / 业务代码 onError 处理(业务流程没问题) 3. 但底层 Promise rejection 仍冒泡到 window.onunhandledrejection 4. 我们的 listener 只读 e.reason,没 preventDefault 5. Chrome runtime 把这个未处理的 rejection 写入 chrome://extensions 错误日志 6. 用户看到 "Failed to fetch" + 我们扩展的 chunk 文件名 → 误判扩展有 bug
为什么堆栈追踪指向 ext-context-guard-DtaikQ0W.js:48:bundle 把 react-is 等代码打到同一个 chunk,Chrome 的 stack trace 取最近的 user 代码位置。
修复¶
让 unhandledrejection listener 区分 3 类:
window.addEventListener('unhandledrejection', (e) => {
const reason: any = e.reason;
const msg = String(reason?.message || reason || '');
// 真 context invalidated → 触发 reload + 阻止冒泡
if (isContextError(msg)) {
trigger();
e.preventDefault();
return;
}
// 业务可恢复的网络错误 → console.warn + 阻止冒泡(不污染 chrome 错误日志)
if (
msg.includes('Failed to fetch') ||
msg.includes('NetworkError') ||
msg.includes('AbortError') ||
msg.includes('Load failed')
) {
console.warn('[ext-context-guard] suppressed network error:', msg);
e.preventDefault();
}
// 其他真 bug → 不动 default action(让 Chrome 仍显示)
});
设计权衡¶
| 方案 | 优点 | 缺点 |
|---|---|---|
| ❌ preventDefault 所有 rejection | chrome 错误页彻底干净 | 真 bug 也被掩盖 |
| ❌ 全部不动 | 真 bug 暴露 | 用户看到误导信息 |
| ✅ 仅 suppress 已知"业务可恢复"错误 | 真 bug 仍暴露 + 用户看不到误判 | 维护一份"已知可忽略"白名单 |
选了方案 ✅。console.warn 保留给开发者 debug。
改动文件¶
| 文件 | 改了什么 |
|---|---|
src/utils/ext-context-guard.ts |
unhandledrejection listener 区分 3 类 |
package.json |
0.10.51 → 0.10.52 |
验证¶
- ✅
pnpm compile0 错 - ✅
pnpm build8.12s - 📋 浏览器实测:触发网络瞬断(如关 WiFi 几秒)后 chrome://extensions 错误页应不再刷屏
如何避免再犯¶
- window.onunhandledrejection listener 永远要决定 preventDefault 或不动 —— 不要"只读"
- 业务可恢复错误的白名单要明确 —— Failed to fetch / AbortError / NetworkError / Load failed
- 真 bug 不要 preventDefault —— 让 Chrome 错误日志显示,方便发现
相关¶
- 0022-extension-context-invalidated — 引入 ext-context-guard 的初衷(与本 issue 同一文件)
- 业务代码 fetch 总数:3 处(dynamic-scraper / use-network-status / batch-controller),全部已 try-catch 兜底