musistudio/claude-code-router · error · Error
Browser automation session tab was not found: ${ref.tabId}
Error message
Browser automation session tab was not found: ${ref.tabId} What it means
Thrown when restoring an unknown session (not in the in-memory sessions map) whose referenced tabId no longer exists in the browser automation state. Session restore requires the target tab to still be live; a dead tab means the session cannot be rehydrated.
Source
Thrown at packages/electron/src/main/browser-automation-mcp.ts:1232
}
return session;
}
private resolveOptionalSession(args: Record<string, unknown>): AttachedSession | undefined {
const ref = readSessionRef(args.session);
if (!ref) {
return undefined;
}
const existing = this.sessions.get(ref.sessionId);
if (existing) {
if (existing.ref.tabId !== ref.tabId) {
throw new Error("Browser automation session tabId does not match the attached session.");
}
return existing;
}
const state = builtInBrowserService.getAutomationState();
if (!state.tabs.some((tab) => tab.id === ref.tabId)) {
throw new Error(`Browser automation session tab was not found: ${ref.tabId}`);
}
const restored: AttachedSession = {
attachedAt: Date.now(),
leaseId: randomUUID(),
observeOnly: false,
ref
};
this.sessions.set(ref.sessionId, restored);
return restored;
}
private assertCanMutate(session?: AttachedSession): void {
if (session?.observeOnly) {
throw new Error("This browser automation session is observeOnly and cannot mutate browser state.");
}
}
private removeSessionsForTab(tabId: string): void {View on GitHub (pinned to 99f24806c6)
Solutions
- Re-attach to a live tab and use the newly returned session object.
- Avoid closing a tab while you still intend to use its session.
- Treat this as a signal to re-discover state (browser_tab_list) rather than retrying the same ref.
Example fix
// before
await call("browser_tab_close", { tabId });
await call("browser_tool", { session: oldSession });
// after
await call("browser_tab_close", { tabId });
const { session } = await call("browser_attach", { tabId: newTabId });
await call("browser_tool", { session }); Defensive patterns
Strategy: fallback
Validate before calling
const { tabs } = await call("browser_tab_list", {});
if (!tabs.some((t) => t.id === session.ref.tabId)) { const { session: s } = await call("browser_attach", { tabId: tabs[0].id }); session = s; }
await call(tool, { session }); Try / catch
try { await call(tool, { session }); } catch (e) { if (e instanceof Error && e.message.includes("session tab was not found")) { const { session: s } = await call("browser_attach", { tabId }); await call(tool, { session: s }); } else throw e; } Prevention
- Re-attach after restarts or tab closures
- Don't close tabs you still need sessions on
- Refresh refs before resuming paused scripts
When it happens
Trigger: Passing a session ref whose tab was closed (closing a tab removes its sessions, so the ref is treated as new), or after the automation browser reopened with fresh tabs while the caller kept an old ref.
Common situations: Long-running scripts that pause and resume; app/browser restart invalidating tab ids; closing a tab mid-workflow and reusing the prior session object in the next call.
Related errors
- Browser tab was not found: ${tabId}
- Unable to resolve browser tab for automation session.
- A valid browser automation session is required.
- Browser automation session tabId does not match the attached
- browser_tab_activate requires tabId or session.
AI-assisted analysis of musistudio/claude-code-router@99f24806c6 (2026-08-27).
Data as JSON: /api/errors/5ede63d73337d160.
Report an issue: GitHub.