jackwener/OpenCLI · info
[opencli] Tab ${tabId} drifted to window ${tab.windowId}, mo
Error message
[opencli] Tab ${tabId} drifted to window ${tab.windowId}, moving back to ${session.windowId} What it means
A console warning from tab resolution when a bound session tab was found in a different window than session.windowId while its URL is still debuggable and the session has no preferred tab. The extension logs this before attempting to move the tab back into the session's window rather than abandoning the binding.
Source
Thrown at extension/src/background.ts:1503
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) {
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',View on GitHub (pinned to 49907e53dc)
Solutions
- Do nothing — the extension auto-moves the tab back; verify the command succeeds
- Avoid dragging the bound tab between windows during automation
- Re-run 'opencli browser bind' to rebind to the tab's current location
- Pin the automation window or use a dedicated profile/window for automation
Defensive patterns
Strategy: fallback
Validate before calling
const tab = await chrome.tabs.get(tabId);
const drifted = tab.windowId !== session.windowId;
if (drifted) console.warn('tab drifted; will be moved back'); Prevention
- Don't drag the automation tab between windows mid-run
- Use a dedicated browser window for automation
- Rebind with 'opencli browser bind' after window restructuring
When it happens
Trigger: User manually drags the bound debug tab into another browser window, or window restore/tab reordering places the tab elsewhere, and a subsequent automation command re-resolves the tab.
Common situations: User interacting with the browser during an automation run; Chrome window restore after crash; multi-window debugging setups.
Related errors
- [opencli] Tab ${tabId} no longer exists, re-resolving
- Failed to create tab lease in automation container
- [opencli] Failed to move tab back: ${moveErr}
- [opencli] Tab ${tabId} URL is not debuggable (${tab.url}), r
- [opencli] data: URI was intercepted (${updated.url}), creati
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/f8d55027b861508c.
Report an issue: GitHub.