{"record":{"id":"3304c0d134c4a6b2","repo":"jackwener/OpenCLI","slug":"bound-tab-not-debuggable","errorCode":"bound_tab_not_debuggable","errorMessage":"Bound tab for session \"${session.session}\" is not debuggable (${preferredTab.url ?? 'unknown URL'}).","messagePattern":"Bound tab for session \"(.+?)\" is not debuggable \\((.+?)\\)\\.","errorType":"error_code","errorClass":"CommandFailure","httpStatus":null,"severity":"error","filePath":"extension/src/background.ts","lineNumber":1537,"sourceCode":"        automationSessions.delete(leaseKey);\n        throw new CommandFailure(\n          'bound_tab_gone',\n          `Bound tab for session \"${existingSession.session}\" no longer exists.`,\n          'Run \"opencli browser bind\" again, then retry the command.',\n        );\n      }\n      console.warn(`[opencli] Tab ${tabId} no longer exists, re-resolving`);\n    }\n  }\n\n  const existingPreferredTabId = existingSession?.preferredTabId ?? null;\n  if (existingSession && existingPreferredTabId !== null) {\n    const session = existingSession;\n    try {\n      const preferredTab = await chrome.tabs.get(existingPreferredTabId);\n      if (isDebuggableUrl(preferredTab.url)) return { tabId: preferredTab.id!, tab: preferredTab };\n      if (!session.owned) {\n        throw new CommandFailure(\n          'bound_tab_not_debuggable',\n          `Bound tab for session \"${session.session}\" is not debuggable (${preferredTab.url ?? 'unknown URL'}).`,\n          'Switch the tab to an http(s) page or run \"opencli browser bind\" on another tab.',\n        );\n      }\n    } catch (err) {\n      if (err instanceof CommandFailure) throw err;\n      await removeLeaseSession(leaseKey);\n      if (!session.owned) {\n        throw new CommandFailure(\n          'bound_tab_gone',\n          `Bound tab for session \"${session.session}\" no longer exists.`,\n          'Run \"opencli browser bind\" again, then retry the command.',\n        );\n      }\n      return createOwnedTabLease(leaseKey, initialUrl);\n    }\n  }","sourceCodeStart":1519,"sourceCodeEnd":1555,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/extension/src/background.ts#L1519-L1555","documentation":"When a bound session has a preferredTabId, resolveTab fetches that preferred tab directly; if it exists but its URL is not debuggable (not http(s)/about:blank/data:), the library throws because CDP cannot attach to browser-internal pages. This is the preferred-tab branch of the same check as error 5210.","triggerScenarios":"existingSession.preferredTabId !== null, chrome.tabs.get succeeds, but preferredTab.url fails isDebuggableUrl (chrome://, edge://, extension page, file://) and the session is unowned.","commonSituations":"The tab bound via 'opencli browser bind' was navigated to chrome://version, a Chrome Web Store page, or an internal new-tab page before running the next command.","solutions":["Switch the bound tab to an http(s) page as the remediation hint says","Re-run 'opencli browser bind' on another tab that shows web content","Navigate programmatically: opencli browser navigate https://…","Keep the bound tab pinned to real web pages during automation"],"exampleFix":"// before\npreferredTab.url = 'chrome://newtab' → bound_tab_not_debuggable\n// after\nopencli browser navigate https://example.com   // then retry","handlingStrategy":"validation","validationCode":"const preferred = await chrome.tabs.get(preferredTabId);\nif (!/^https?:/i.test(preferred.url ?? '')) {\n  await chrome.tabs.update(preferredTabId, { url: 'https://example.com' });\n}","typeGuard":"function isWebUrl(url?: string): boolean {\n  return !!url && (url.startsWith('http://') || url.startsWith('https://'));\n}","tryCatchPattern":"try {\n  await cmd();\n} catch (e) {\n  if ((e as Error).message.includes('not debuggable')) {\n    await chrome.tabs.update(tabId, { url: START_URL });\n    await retry(cmd);\n  } else throw e;\n}","preventionTips":["Avoid typing chrome:// URLs into the automation tab","Navigate programmatically back to http(s) before commands","Monitor tab URL changes with chrome.tabs.onUpdated and re-bind when the URL becomes non-web","Use a dedicated profile/window for automation"],"tags":["chrome-extension","debugging","cdp","session-binding"],"backgroundTag":"tab-not-debuggable","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}