跳转至

[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 详情页"错误"区看到:

TypeError: Failed to fetch
上下文 main.html
堆栈追踪 chunks/ext-context-guard-DtaikQ0W.js:48

直观结论 = 扩展坏了,但实际上业务代码已经 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 compile 0 错
  • pnpm build 8.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 兜底