musistudio/claude-code-router · error · Error
browser_navigate could not resolve an active tab.
Error message
browser_navigate could not resolve an active tab.
What it means
Thrown by the browser_navigate MCP tool when tabId, session ref, and the browser's activeTabId are all unresolvable. Unlike tab_activate/tab_close, navigate does fall back to the currently active tab — this error means the automation browser has no active tab at all (e.g. all tabs were closed or the window state is empty).
Source
Thrown at packages/electron/src/main/browser-automation-mcp.ts:815
case "browser_tab_close": {
await this.ensureBrowserOpen();
const session = this.resolveOptionalSession(args);
this.assertCanMutate(session);
const tabId = readString(args.tabId) || session?.ref.tabId;
if (!tabId) {
throw new Error("browser_tab_close requires tabId or session.");
}
const state = builtInBrowserService.closeAutomationTab(tabId);
this.removeSessionsForTab(tabId);
return browserWindowState(state);
}
case "browser_navigate": {
await this.ensureBrowserOpen();
const session = this.resolveOptionalSession(args);
this.assertCanMutate(session);
const tabId = readString(args.tabId) || session?.ref.tabId || builtInBrowserService.getAutomationState().activeTabId;
if (!tabId) {
throw new Error("browser_navigate could not resolve an active tab.");
}
const url = requiredString(args.url, "browser_navigate requires url.");
const waitUntil = normalizeWaitUntil(readString(args.waitUntil), "interactive");
const readiness = await waitForReadiness(
builtInBrowserService.getAutomationWebContents(tabId),
waitUntil,
clampInteger(readNumber(args.timeoutMs) ?? defaultWaitTimeoutMs, 100, 120000),
() => builtInBrowserService.navigateAutomationTab(url, tabId),
url
);
const state = builtInBrowserService.getAutomationState();
const webContents = builtInBrowserService.getAutomationWebContents(tabId);
const handoff = await maybeRequestHandoffAfterNavigation(webContents, readiness, {
requestedUrl: url,
session: session?.ref,
tabId,
waitUntil
});View on GitHub (pinned to 99f24806c6)
Solutions
- Call browser_navigate with an explicit url but no tabId — it will create a tab when one is absent — or call browser_open first to establish state.
- Pass tabId from a prior browser_tab_list/browser_navigate result.
- Attach a session (which pins a tabId) before closing tabs in a script.
Example fix
// before
await call("browser_tab_close", { tabId });
await call("browser_navigate", { url }); // no active tab left
// after
await call("browser_tab_close", { tabId });
await call("browser_navigate", { url, tabId: newTabId }); // or create tab via browser_navigate url flow Defensive patterns
Strategy: fallback
Validate before calling
const state = await call("browser_tab_list", {});
if (!state.tabs.length) { await call("browser_open", { url: "about:blank" }); } // ensure a tab exists
await call("browser_navigate", { url }); Try / catch
try { await call("browser_navigate", { url }); } catch (e) { if (e instanceof Error && e.message.includes("could not resolve an active tab")) { await call("browser_open", { url }); } else throw e; } Prevention
- Open a tab before navigating
- Pass explicit tabId in multi-tab scripts
- Recover by opening rather than retrying blindly
When it happens
Trigger: Calling browser_navigate with no tabId and no session when builtInBrowserService.getAutomationState().activeTabId is null — typically right after the last tab was closed while the hidden browser stayed open.
Common situations: A multi-step automation script closes the working tab, then navigates; the hidden automation browser was opened with no initial tab.
Related errors
- Unable to resolve browser tab for automation session.
- browser_tab_activate requires tabId or session.
- browser_tab_close requires tabId or session.
- Chrome login import job was not found: ${jobId}
- Unknown browser automation tool: ${name}
AI-assisted analysis of musistudio/claude-code-router@99f24806c6 (2026-08-27).
Data as JSON: /api/errors/1bca568775ec260c.
Report an issue: GitHub.