musistudio/claude-code-router · error · Error
Browser tab was not found: ${tabId}
Error message
Browser tab was not found: ${tabId} What it means
Thrown at the start of the main browser automation tool run when args.tabId is provided but does not match any tab in the automation browser's state. It is an explicit-target validation: an unknown tab id is rejected immediately rather than creating a new tab.
Source
Thrown at packages/electron/src/main/browser-automation-mcp.ts:1117
await builtInBrowserService.openHidden(await loadAppConfig());
return builtInBrowserService.getAutomationState();
}
private async ensureBrowserVisible(): Promise<BuiltInBrowserState> {
await builtInBrowserService.open(await loadAppConfig());
return builtInBrowserService.getAutomationState();
}
private async openSession(args: Record<string, unknown>): Promise<unknown> {
let state = await this.ensureBrowserOpen();
const url = readString(args.url);
const requestedTabId = readString(args.tabId);
const previousActiveTabId = state.activeTabId;
let tabId = requestedTabId;
let createdTab = false;
if (tabId && !state.tabs.some((tab) => tab.id === tabId)) {
throw new Error(`Browser tab was not found: ${tabId}`);
}
if (!tabId && url) {
const tab = builtInBrowserService.createAutomationTab();
tabId = tab.id;
createdTab = true;
} else if (!tabId) {
tabId = state.activeTabId || builtInBrowserService.createAutomationTab().id;
createdTab = !state.activeTabId;
} else if (state.activeTabId !== tabId) {
builtInBrowserService.selectAutomationTab(tabId);
}
if (!tabId) {
throw new Error("Unable to resolve browser tab for automation session.");
}
const waitUntil = normalizeWaitUntil(readString(args.waitUntil), url ? "interactive" : "none");View on GitHub (pinned to 99f24806c6)
Solutions
- Re-fetch current tab state via browser_tab_list and use a live tabId.
- If you want a new tab, omit tabId and pass url so one is created.
- Handle this error in scripts by re-querying state instead of retrying the same stale id.
Example fix
// before
await call("browser_navigate", { url, tabId: cachedTabId }); // tab was closed
// after
const { tabs } = await call("browser_tab_list", {});
const live = tabs.find((t) => t.url.includes("example.com")) ?? tabs[0];
await call("browser_navigate", { url, tabId: live?.id }); Defensive patterns
Strategy: fallback
Validate before calling
const { tabs } = await call("browser_tab_list", {});
if (!tabs.some((t) => t.id === tabId)) { tabId = tabs[0]?.id; } // refresh stale id
await call("browser_navigate", { url, tabId }); Try / catch
try { await call("browser_navigate", { url, tabId }); } catch (e) { if (e instanceof Error && e.message.includes("Browser tab was not found")) { const { tabs } = await call("browser_tab_list", {}); await call("browser_navigate", { url, tabId: tabs[0]?.id }); } else throw e; } Prevention
- Re-validate cached tab ids before use
- Omit tabId + pass url to create a tab when unsure
- Treat tab closures as invalidating script state
When it happens
Trigger: Passing a tabId from a stale prior session after tabs were closed, from a different browser instance, or a fabricated/mistyped id.
Common situations: Scripts cache tab ids across steps; a tab crashes or is closed mid-script between obtaining the id and using it; the automation browser was reopened resetting tab ids.
Related errors
- Browser automation session tabId does not match the attached
- Browser automation session tab was not found: ${ref.tabId}
- browser_tab_activate requires tabId or session.
- browser_tab_close requires tabId or session.
- browser_navigate could not resolve an active tab.
AI-assisted analysis of musistudio/claude-code-router@99f24806c6 (2026-08-27).
Data as JSON: /api/errors/9ebbf35c348acb7a.
Report an issue: GitHub.