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

  1. 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.
  2. Pass tabId from a prior browser_tab_list/browser_navigate result.
  3. 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

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


AI-assisted analysis of musistudio/claude-code-router@99f24806c6 (2026-08-27). Data as JSON: /api/errors/1bca568775ec260c. Report an issue: GitHub.