openclaw/openclaw · error · BrowserError

browser server not started

Error message

browser server not started

What it means

Thrown by buildBrowserStatus in the browser status route. ctx.state() is expected to return the live browser server state; if it throws, the server was never started or has been torn down, and the route responds HTTP 503 with this BrowserError. It is a service-availability signal, not a per-request validation error.

Source

Thrown at extensions/browser/src/browser/routes/basic.ts:149

    const service = createBrowserProfilesService(params.ctx);
    const result = await params.run(service);
    params.res.json(result);
  } catch (err) {
    return handleBrowserRouteError(params.res, err);
  }
}

async function buildBrowserStatus(
  ctx: BrowserRouteContext,
  profileCtx: ProfileContext,
  signal: AbortSignal,
) {
  signal.throwIfAborted();
  let current: ReturnType<typeof ctx.state>;
  try {
    current = ctx.state();
  } catch {
    throw new BrowserError("browser server not started", 503);
  }

  const capabilities = getBrowserProfileCapabilities(profileCtx.profile);
  const [cdpHttp, cdpReady, pageReady] = capabilities.usesChromeMcp
    ? await (async () => {
        const statusStartedAtMs = Date.now();
        const transportReady = await profileCtx.isTransportAvailable(
          STATUS_CHROME_MCP_TRANSPORT_TIMEOUT_MS,
          signal,
        );
        if (!transportReady) {
          return [false, false, false] as const;
        }
        // Status-safe page probe: ephemeral so a passive status call does not seed
        // a persistent cached Chrome MCP session. Keep the whole status route inside
        // the public client timeout; page probe failures degrade to pageReady=false.
        const pageReachable = await probeChromeMcpPageReady(
          profileCtx,

View on GitHub (pinned to 01804a7531)

Solutions

  1. Wait for the browser server / gateway to finish starting before querying status.
  2. Verify browser.enabled=true and that configuration loaded without errors (check gateway logs).
  3. If the server was intentionally stopped, restart it before calling status endpoints.
  4. Treat HTTP 503 from this route as transient and retry with backoff.
Defensive patterns

Strategy: try-catch

Validate before calling

async function isBrowserServerUp(getState: () => unknown): Promise<boolean> {
  try {
    getState();
    return true;
  } catch {
    return false;
  }
}

Try / catch

try {
  const status = await fetch('/browser/status').then(r => r.json());
} catch (err) {
  if (err instanceof Error && /browser server not started/.test(err.message)) {
    // transient: wait for gateway startup, then retry with backoff
    await backoffRetry();
  } else throw err;
}

Prevention

When it happens

Trigger: Calling GET /status (or any route that builds browser status) before the browser server has been initialized, after it has been stopped, or while it is mid-shutdown. Also triggered if browser.enabled is false so the server object was never created.

Common situations: Probing status during startup before the browser plugin finishes initializing; race between shutdown and a status poll; misconfiguration that disables the browser; running in an environment where the browser server failed to bind.

Related errors


AI-assisted analysis of openclaw/openclaw@01804a7531 (2026-08-12). Data as JSON: /api/errors/64882c23d9ef567e. Report an issue: GitHub.