跳转至

[ISSUE-0022] Extension context invalidated 错误未处理

用户感知的现象

错误日志面板看到大量 Error: Extension context invalidated. 报错 堆栈指向 React internals chunk 主面板 / popup 可能卡死或部分功能失灵

根因分析

Chrome MV3 扩展的经典痛点。

触发链路: 1. 用户在 chrome://extensions 点「刷新」(或 dev 模式热重载、扩展自动更新、disable/enable) 2. Service Worker 重启 → 拿到新的 extension context ID 3. 老的 main.html / popup / settings 标签页还开着 —— 它们的 React 代码持有的 chrome.runtime / browser.* 是上一个 context 4. 老页面继续调 browser.runtime.sendMessage / storage.getItem 等 → 全部抛 Extension context invalidated 5. React useRequest / useEffect 异常 → 错误冒泡到 error boundary 或 console

为什么之前没修: - 错误日志面板(content script 注入的)只是显示给用户看,不影响代码运行 - 真正 broken 的是 polling / 监听器(如 sidebar dataCounts 轮询、settings 自动保存) - 用户没主动反馈过,直到 v0.10.27 推 github + 频繁 reload 导致暴露

修复方案

写一个全局 ext-context-guard.ts,在所有 entry 启动时安装:

1. 检测函数

function isContextValid(): boolean {
  try {
    // chrome.runtime.id 访问会在 invalidated 时抛错或返回 undefined
    return !!chrome?.runtime?.id;
  } catch {
    return false;
  }
}

2. 全局 error listener

function installContextGuard() {
  const handle = (msg: string) => {
    if (!msg.includes('Extension context invalidated')) return;
    showOverlay();
    setTimeout(() => location.reload(), 1500);
  };

  window.addEventListener('error', (e) => handle(e.message || ''));
  window.addEventListener('unhandledrejection', (e) => handle(String(e.reason?.message || e.reason || '')));

  // 周期性检查(5 秒一次),抓住静默失效(如 polling 内部 catch 吞了错)
  setInterval(() => {
    if (!isContextValid()) {
      showOverlay();
      setTimeout(() => location.reload(), 1500);
    }
  }, 5000);
}

3. UI 覆盖层

显示「扩展已更新,正在刷新...」让用户知道发生了什么,避免「页面突然 reload」的困惑感。1.5 秒后自动 reload。

4. 在所有 entry 注入

main / popup / settings / results 4 个 entry 启动时调 installContextGuard()

改动文件

文件 改了什么
src/utils/ext-context-guard.ts 🆕 guard 主逻辑 + overlay UI
src/entrypoints/main/main.tsx 启动时 installContextGuard
src/entrypoints/popup/main.tsx 同上
src/entrypoints/settings/main.tsx 同上
src/entrypoints/results/main.tsx 同上

验证方式

  1. 加载扩展 + 打开主面板
  2. chrome://extensions 点扩展「刷新」按钮
  3. 老主面板 tab 应:
  4. 显示「扩展已更新,正在刷新...」覆盖层
  5. 1.5 秒后自动 reload
  6. reload 后页面正常(新 context)
  7. 错误日志不再堆积 Extension context invalidated

如何避免再犯

  • Chrome MV3 扩展必装 context guard:任何长寿命 tab(main / settings 独立窗口)都暴露在此风险
  • 全局 error listener 是兜底:单点 try/catch 太散,不可能每个 sendMessage 都包
  • 5 秒 setInterval 是双保险:万一 listener 漏抓(被某层 catch 吞了),周期检查能抓到

相关问题

无 — Chrome MV3 通用问题,与项目业务逻辑无关。