jackwener/OpenCLI · error · CommandFailure
Bound tab for session "${session.session}" is not debuggable
Error message
Bound tab for session "${session.session}" is not debuggable (${tab.url ?? 'unknown URL'}). What it means
resolveTab() found an existing bound (unowned) browser automation session and a candidate tab whose window matches, but the tab's URL is not debuggable (not http(s)/about:blank/data:). The library throws because CDP debugging cannot attach to such tabs (chrome://, chrome-extension://, file://, etc.), so honoring the binding would silently break later commands.
Source
Thrown at extension/src/background.ts:1492
type ResolvedTab = { tabId: number; tab: chrome.tabs.Tab | null };
/**
* Resolve target tab for the session lease, returning both the tabId and
* the Tab object (when available) so callers can skip a redundant chrome.tabs.get().
*/
async function resolveTab(tabId: number | undefined, leaseKey: string, initialUrl?: string): Promise<ResolvedTab> {
const existingSession = automationSessions.get(leaseKey);
// Even when an explicit tabId is provided, validate it is still debuggable.
if (tabId !== undefined) {
try {
const tab = await chrome.tabs.get(tabId);
const session = existingSession;
const matchesSession = session
? (session.preferredTabId !== null ? session.preferredTabId === tabId : tab.windowId === session.windowId)
: false;
if (isDebuggableUrl(tab.url) && matchesSession) return { tabId, tab };
if (session && !session.owned) {
throw new CommandFailure(
matchesSession ? 'bound_tab_not_debuggable' : 'bound_tab_mismatch',
matchesSession
? `Bound tab for session "${session.session}" is not debuggable (${tab.url ?? 'unknown URL'}).`
: `Target tab is not the tab bound to session "${session.session}".`,
'Run "opencli browser bind" again on a debuggable http(s) tab.',
);
}
if (session && !matchesSession && session.preferredTabId === null && isDebuggableUrl(tab.url)) {
// Tab drifted to another window but content is still valid.
// Try to move it back instead of abandoning it.
console.warn(`[opencli] Tab ${tabId} drifted to window ${tab.windowId}, moving back to ${session.windowId}`);
try {
await chrome.tabs.move(tabId, { windowId: session.windowId, index: -1 });
const moved = await chrome.tabs.get(tabId);
if (moved.windowId === session.windowId && isDebuggableUrl(moved.url)) {
return { tabId, tab: moved };
}
} catch (moveErr) {View on GitHub (pinned to 49907e53dc)
Solutions
- Navigate the bound tab back to an http(s) page
- Re-run 'opencli browser bind' on a debuggable http(s) tab as the remediation hint says
- Bind a different tab that stays on http(s) content
- Disable auto-redirects/extensions that force the tab onto chrome:// pages
Example fix
// before cmd opencli browser click .btn // bound tab now on chrome://history // after opencli browser navigate https://example.com // put bound tab back on http(s), then retry
Defensive patterns
Strategy: validation
Validate before calling
const tab = await chrome.tabs.get(tabId);
const ok = !tab.url || tab.url.startsWith('http://') || tab.url.startsWith('https://') || tab.url === 'about:blank' || tab.url.startsWith('data:');
if (!ok) throw new Error(`tab ${tabId} not debuggable: ${tab.url}`); Type guard
function isDebuggableUrl(url?: string): boolean {
return !url || url.startsWith('http://') || url.startsWith('https://') || url === 'about:blank' || url.startsWith('data:');
} Try / catch
try {
await cmd();
} catch (e) {
if ((e as Error).message.includes('is not debuggable')) await rebindToHttpTab();
else throw e;
} Prevention
- Keep the bound tab on http(s) pages during automation
- Re-bind after manually navigating the tab
- Check tab.url before each command in a wrapper
- Pin the automation tab to avoid user interference
When it happens
Trigger: A command resolves a tab via resolveTab while a bind-session exists with preferredTabId matching or windowId matching, and the current tab.url fails isDebuggableUrl (e.g. user navigated the bound tab to chrome://settings).
Common situations: User manually navigates the bound tab to a browser settings page, a new-tab page (chrome://newtab), a PDF viewer, or an extension page after running 'opencli browser bind'.
Related errors
- bound_tab_not_debuggable
- Cannot debug tab ${tabId}: URL is ${tab.url ?? 'unknown'}
- bound_tab_gone
- Tab ${tabId} no longer exists
- attach failed: ${lastError}${hint}
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/f7ea7ad69128b9b3.
Report an issue: GitHub.