jackwener/OpenCLI · error · CommandFailure
bound_window_operation_blocked
bound_window_operation_blocked
Error message
Session "${existing.session}" is bound to a user tab and does not own an OpenCLI tab lease. What it means
getAutomationWindow looks up the lease's automation session; if the session exists but is only bound to a user tab (existing.owned === false), the session does not own an OpenCLI-managed window/tab group, so window-level operations are refused with CommandFailure code 'bound_window_operation_blocked'. The library distinguishes owned automation windows from user-bound tabs and only allows window operations on the former.
Source
Thrown at extension/src/background.ts:1129
kind: 'owned',
windowId: sessionWindowId,
owned: true,
preferredTabId: tabId,
});
resetWindowIdleTimer(leaseKey);
return { tabId, tab };
}
/** Get or create the dedicated automation container window.
* This compatibility helper returns the shared owned container. Leases
* lease tabs inside it instead of owning separate windows.
*/
async function getAutomationWindow(leaseKey: string, initialUrl?: string): Promise<number> {
// Check if our window is still alive.
const existing = automationSessions.get(leaseKey);
if (existing) {
if (!existing.owned) {
throw new CommandFailure(
'bound_window_operation_blocked',
`Session "${existing.session}" is bound to a user tab and does not own an OpenCLI tab lease.`,
'Use page commands on the bound tab, or unbind the session first.',
);
}
try {
const tabId = existing.preferredTabId;
if (tabId !== null) {
const tab = await chrome.tabs.get(tabId);
if (isDebuggableUrl(tab.url)) return tab.windowId;
}
await chrome.windows.get(existing.windowId);
return existing.windowId;
} catch {
// Tab/window was closed by user
await removeLeaseSession(leaseKey);
}
}View on GitHub (pinned to 49907e53dc)
Solutions
- Use page-level commands on the bound tab instead of window-level commands
- Unbind the session (unbind command) and re-open it as an owned automation window
- Create a new named session via the normal open flow so it owns its own window/tab group
Example fix
// before
await runCommand('mysession', 'window resize', { width: 1280 });
// after
const mode = await getSessionMode('mysession'); // 'owned' | 'bound'
if (mode === 'bound') await runCommand('mysession', 'unbind');
await runCommand('mysession', 'window resize', { width: 1280 }); Defensive patterns
Strategy: try-catch
Validate before calling
// before window-level commands, check ownership
const owned = await isOwnedAutomationSession(sessionName); // e.g. via status command
if (!owned) console.warn('Session is bound to a user tab; window commands will be blocked'); Try / catch
try {
await windowCommand(session);
} catch (e) {
if (e.code === 'bound_window_operation_blocked') {
console.error('Use page commands on the bound tab, or unbind and reopen as an owned session');
} else throw e;
} Prevention
- Only issue window-level commands to sessions created through the owned open flow
- Check session status (owned vs bound) before window operations
- After a group/window is dissolved, re-open the session rather than reusing a bound lease
When it happens
Trigger: Running a window-level automation command (resize, focus, snapshot, etc.) against a session that was previously bound to a regular user tab rather than created as an owned automation window — getAutomationWindow detects existing && !existing.owned and throws.
Common situations: Attaching the automation session to a manually opened browser tab, then trying window commands on it; a lease got downgraded from owned to bound after its group/window was dissolved; scripts assuming every session owns a window.
Related errors
- Band band_session cookie missing
- ${probe.detail}
- No posts found in this Band
- Browser session required for bilibili follow
- Browser session required for bilibili following
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/57d9b0dbe0a98032.
Report an issue: GitHub.