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

  1. Navigate the bound tab back to an http(s) page
  2. Re-run 'opencli browser bind' on a debuggable http(s) tab as the remediation hint says
  3. Bind a different tab that stays on http(s) content
  4. 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

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


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/f7ea7ad69128b9b3. Report an issue: GitHub.