jackwener/OpenCLI · error · CommandFailure
bound_tab_gone
bound_tab_gone
Error message
Bound tab for session "${existingSession.session}" no longer exists. What it means
During tab re-resolution, chrome.tabs.get for the candidate tab threw (tab was closed or unreachable) while an existing unowned bound session pointed at it. The library deletes the stale lease and throws bound_tab_gone so the caller knows the session binding is dead and must be recreated.
Source
Thrown at extension/src/background.ts:1520
// 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) {
console.warn(`[opencli] Failed to move tab back: ${moveErr}`);
}
} else if (!isDebuggableUrl(tab.url)) {
console.warn(`[opencli] Tab ${tabId} URL is not debuggable (${tab.url}), re-resolving`);
}
} catch (err) {
if (err instanceof CommandFailure) throw err;
if (existingSession && !existingSession.owned) {
automationSessions.delete(leaseKey);
throw new CommandFailure(
'bound_tab_gone',
`Bound tab for session "${existingSession.session}" no longer exists.`,
'Run "opencli browser bind" again, then retry the command.',
);
}
console.warn(`[opencli] Tab ${tabId} no longer exists, re-resolving`);
}
}
const existingPreferredTabId = existingSession?.preferredTabId ?? null;
if (existingSession && existingPreferredTabId !== null) {
const session = existingSession;
try {
const preferredTab = await chrome.tabs.get(existingPreferredTabId);
if (isDebuggableUrl(preferredTab.url)) return { tabId: preferredTab.id!, tab: preferredTab };
if (!session.owned) {
throw new CommandFailure(
'bound_tab_not_debuggable',View on GitHub (pinned to 49907e53dc)
Solutions
- Re-run 'opencli browser bind' to create a fresh binding, then retry the command
- Reopen the tab if it was closed accidentally and rebind
- Check that the browser window containing the bound tab is still open
- Avoid closing the bound tab while automation sessions reference it
Example fix
// before Tab closed → bound_tab_gone // after opencli browser bind // rebind to a live tab, then retry the original command
Defensive patterns
Strategy: retry
Validate before calling
let tabExists = false;
try { await chrome.tabs.get(tabId); tabExists = true; } catch {}
if (!tabExists) await rebind(); Type guard
async function tabExists(tabId: number): Promise<boolean> {
try { await chrome.tabs.get(tabId); return true; } catch { return false; }
} Try / catch
try {
await cmd();
} catch (e) {
if ((e as Error).message.includes('no longer exists')) { await opencliBind(); await retry(cmd); }
else throw e;
} Prevention
- Don't close tabs while a bind session is active
- Re-bind after browser restarts
- Check tab existence before each automated step
- Keep bound tabs in a dedicated window
When it happens
Trigger: chrome.tabs.get(tabId) rejects inside resolveTab's catch block for a tab belonging to an existing unowned (bound) session — i.e. the user closed the bound tab before the command ran.
Common situations: User closes the tab that 'opencli browser bind' bound to, then runs another opencli browser command; tab discarded by window close; tab crashed.
Related errors
- Bound tab for session "${session.session}" is not debuggable
- bound_tab_not_debuggable
- Tab ${tabId} no longer exists
- No targetId for tab ${tabId} — page may have been closed
- Requires up-to-date Chrome extension (nativeClick).
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/95a142423d573473.
Report an issue: GitHub.