{"record":{"id":"64882c23d9ef567e","repo":"openclaw/openclaw","slug":"browser-server-not-started","errorCode":null,"errorMessage":"browser server not started","messagePattern":"browser server not started","errorType":"exception","errorClass":"BrowserError","httpStatus":503,"severity":"error","filePath":"extensions/browser/src/browser/routes/basic.ts","lineNumber":149,"sourceCode":"    const service = createBrowserProfilesService(params.ctx);\n    const result = await params.run(service);\n    params.res.json(result);\n  } catch (err) {\n    return handleBrowserRouteError(params.res, err);\n  }\n}\n\nasync function buildBrowserStatus(\n  ctx: BrowserRouteContext,\n  profileCtx: ProfileContext,\n  signal: AbortSignal,\n) {\n  signal.throwIfAborted();\n  let current: ReturnType<typeof ctx.state>;\n  try {\n    current = ctx.state();\n  } catch {\n    throw new BrowserError(\"browser server not started\", 503);\n  }\n\n  const capabilities = getBrowserProfileCapabilities(profileCtx.profile);\n  const [cdpHttp, cdpReady, pageReady] = capabilities.usesChromeMcp\n    ? await (async () => {\n        const statusStartedAtMs = Date.now();\n        const transportReady = await profileCtx.isTransportAvailable(\n          STATUS_CHROME_MCP_TRANSPORT_TIMEOUT_MS,\n          signal,\n        );\n        if (!transportReady) {\n          return [false, false, false] as const;\n        }\n        // Status-safe page probe: ephemeral so a passive status call does not seed\n        // a persistent cached Chrome MCP session. Keep the whole status route inside\n        // the public client timeout; page probe failures degrade to pageReady=false.\n        const pageReachable = await probeChromeMcpPageReady(\n          profileCtx,","sourceCodeStart":131,"sourceCodeEnd":167,"githubUrl":"https://github.com/openclaw/openclaw/blob/01804a75319da4b69c9ab98ceaa30477e22b8c0b/extensions/browser/src/browser/routes/basic.ts#L131-L167","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Wait for the browser server / gateway to finish starting before querying status.","Verify browser.enabled=true and that configuration loaded without errors (check gateway logs).","If the server was intentionally stopped, restart it before calling status endpoints.","Treat HTTP 503 from this route as transient and retry with backoff."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"async function isBrowserServerUp(getState: () => unknown): Promise<boolean> {\n  try {\n    getState();\n    return true;\n  } catch {\n    return false;\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  const status = await fetch('/browser/status').then(r => r.json());\n} catch (err) {\n  if (err instanceof Error && /browser server not started/.test(err.message)) {\n    // transient: wait for gateway startup, then retry with backoff\n    await backoffRetry();\n  } else throw err;\n}","preventionTips":["Treat HTTP 503 from the status route as transient; retry with exponential backoff.","Confirm browser.enabled=true and the gateway finished startup before polling status.","Log the underlying ctx.state() failure from gateway logs when this persists."],"tags":["lifecycle","browser-server","http-503","availability"],"backgroundTag":null,"analyzedSha":"01804a75319da4b69c9ab98ceaa30477e22b8c0b","analyzedAt":"2026-08-12T04:37:58.197Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}