can1357/oh-my-pi · error · ToolError

Shared browser daemon unavailable (broker start or Chromium

Error message

Shared browser daemon unavailable (broker start or Chromium launch failed); check `hub ps` for omp.browser.* daemons and ~/.omp/logs for details

What it means

openSharedHeadlessHandle asks the shared-browser broker to start (or join) a shared headless Chromium daemon. If the broker fails to start or the Chromium launch fails, the broker returns null and this ToolError is thrown, directing the user to inspect `hub ps` for omp.browser.* daemons and ~/.omp/logs for the underlying cause.

Source

Thrown at packages/coding-agent/src/tools/browser/registry.ts:414

 * Attach to the project-shared broker-owned Chromium. Failures surface as
 * `ToolError` — a CLI-host process never silently falls back to a private
 * Chromium, so a broken broker cannot quietly recreate per-process launch
 * storms.
 */
async function openSharedHeadlessHandle(
	kind: Extract<PuppeteerBrowserKind, { kind: "headless" }>,
	opts: AcquireBrowserOptions,
): Promise<PuppeteerBrowserHandle> {
	const vp = opts.viewport ?? DEFAULT_VIEWPORT;
	try {
		const shared = await ensureSharedBrowser({
			projectDir: opts.cwd,
			headless: kind.headless,
			viewport: vp,
			signal: opts.signal,
		});
		if (!shared) {
			throw new ToolError(
				"Shared browser daemon unavailable (broker start or Chromium launch failed); check `hub ps` for omp.browser.* daemons and ~/.omp/logs for details",
			);
		}
		const puppeteer = await loadPuppeteer();
		const browser = await puppeteer.connect({
			browserWSEndpoint: shared.wsEndpoint,
			defaultViewport: kind.headless
				? {
						width: vp.width,
						height: vp.height,
						deviceScaleFactor: vp.deviceScaleFactor ?? DEFAULT_VIEWPORT.deviceScaleFactor,
					}
				: null,
			protocolTimeout: BROWSER_PROTOCOL_TIMEOUT_MS,
		});
		// Attaching to the shared daemon is the natural point to sweep targets
		// left behind by omp processes that died without teardown — bounds
		// accumulation without a background timer. Best-effort and detached so a

View on GitHub (pinned to 9690622007)

Solutions

  1. Run `hub ps` to see whether omp.browser.* daemons exist; clear stale daemons and retry
  2. Inspect ~/.omp/logs for the broker/Chromium launch error and fix the root cause (missing libs, disk space, permissions)
  3. Fall back to a non-shared browser kind (spawned browser) if sharing is not required
  4. Retry after freeing resources (memory/disk) if the launch failed due to limits
Defensive patterns

Strategy: fallback

Validate before calling

// check broker/daemon state before requesting a shared browser
const ps = Bun.spawnSync(["hub", "ps"], { stdout: "pipe" });
const hasDaemon = ps.stdout.toString().includes("omp.browser.");
if (!hasDaemon) console.warn("No shared browser daemon running; expect broker cold start");

Try / catch

try {
  return await openSharedHeadlessHandle(kind, opts);
} catch (err) {
  if (err instanceof ToolError && err.message.includes("Shared browser daemon unavailable")) {
    return openDedicatedBrowserHandle(opts); // fall back to non-shared spawn
  }
  throw err;
}

Prevention

When it happens

Trigger: Requesting a shared headless browser when the broker daemon cannot start (missing hub/broker, permission issues) or Chromium cannot be launched (missing system libraries, no writable profile dir, resource limits).

Common situations: CI containers missing Chromium shared-library dependencies; read-only or full disk preventing the daemon profile dir; broker crashed previously leaving stale state; headless servers without GPU/fonts; concurrent daemons exhausting memory.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/fb375645e8ea8e4d. Report an issue: GitHub.