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
- 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.
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
- 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.
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
- browser not running
- Browser profile "${params.profileCtx.profile.name}" could no
- Browser profile "${params.profileCtx.profile.name}" could no
- Claude CLI credential input is no longer available
- OpenClaw Chrome extension is not connected to the relay
AI-assisted analysis of openclaw/openclaw@01804a7531 (2026-08-12).
Data as JSON: /api/errors/64882c23d9ef567e.
Report an issue: GitHub.