{"record":{"id":"eb1688f6483e1bea","repo":"can1357/oh-my-pi","slug":"shared-browser-attach-failed-err-instanceof-err","errorCode":null,"errorMessage":"Shared browser attach failed: ${err instanceof Error ? err.message : String(err)}","messagePattern":"Shared browser attach failed: (.+?)","errorType":"exception","errorClass":"ToolError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/tools/browser/registry.ts","lineNumber":446,"sourceCode":"\t\t\tprotocolTimeout: BROWSER_PROTOCOL_TIMEOUT_MS,\n\t\t});\n\t\t// Attaching to the shared daemon is the natural point to sweep targets\n\t\t// left behind by omp processes that died without teardown — bounds\n\t\t// accumulation without a background timer. Best-effort and detached so a\n\t\t// slow reap never delays the open (issue #10022).\n\t\tvoid reapOrphanSharedTargets(browser, { projectDir: shared.projectDir, daemonName: shared.daemonName });\n\t\treturn {\n\t\t\tkey: browserKey(kind),\n\t\t\tkind,\n\t\t\tbrowser,\n\t\t\tsharedDaemon: { name: shared.daemonName, projectDir: shared.projectDir },\n\t\t\trefCount: 0,\n\t\t\tstealth: { browserSession: null, override: null },\n\t\t};\n\t} catch (err) {\n\t\tif (err instanceof ToolAbortError || err instanceof ToolError) throw err;\n\t\tif (opts.signal?.aborted) throw new ToolAbortError(\"Browser open aborted\");\n\t\tthrow new ToolError(`Shared browser attach failed: ${err instanceof Error ? err.message : String(err)}`);\n\t}\n}\n\n/** Test-only accessor for the module-global browsers map. */\nexport function getBrowsersMapForTest(): ReadonlyMap<string, BrowserHandle> {\n\treturn browsers;\n}\n","sourceCodeStart":428,"sourceCodeEnd":454,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/tools/browser/registry.ts#L428-L454","documentation":"The final catch-all of openSharedHeadlessHandle: any exception during shared-daemon setup that is not already a ToolAbortError/ToolError and is not explained by an aborted signal is wrapped as ToolError(`Shared browser attach failed: <message>`). It preserves the underlying message (from puppeteer.connect, broker RPC, etc.) while giving it a uniform tool-level shape.","triggerScenarios":"puppeteer.connect({browserWSEndpoint: shared.wsEndpoint}) throwing (daemon died between start and connect), broker RPC returning unexpected results, race where the daemon exits while refCount bookkeeping runs, or any unexpected exception in the attach path.","commonSituations":"Shared daemon crashed or was killed (OOM, hub stop) right after start; wsEndpoint stale after daemon restart; concurrent opens racing daemon teardown; transient network/socket errors to the daemon.","solutions":["Read the wrapped <message> in ~/.omp/logs and fix the root cause (usually daemon crash or stale endpoint)","Stop stale daemons (`hub ps`, then stop/kill omp.browser.* daemons) and retry the open","Retry the open — transient races between daemon start and attach usually resolve","Use a dedicated spawned browser instead of the shared daemon if sharing keeps failing"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// confirm the shared endpoint is still alive before attaching\nconst alive = await fetch(`http://${daemonHost}/json/version`).then(r => r.ok).catch(() => false);\nif (!alive) console.warn(\"Shared daemon endpoint dead; restart it before opening\");","typeGuard":null,"tryCatchPattern":"try {\n  return await openSharedHeadlessHandle(kind, opts);\n} catch (err) {\n  if (err instanceof ToolError && err.message.startsWith(\"Shared browser attach failed:\")) {\n    // log err.message for root cause; restart stale daemons and retry once\n  }\n  throw err;\n}","preventionTips":["Stop stale omp.browser.* daemons (hub ps) before long test runs","Watch ~/.omp/logs for daemon OOM/crash patterns","Avoid concurrent opens racing daemon restarts; serialize first-open","Fall back to a dedicated spawned browser when sharing is unstable"],"tags":["browser","shared-daemon","attach","puppeteer","websocket"],"backgroundTag":"daemon-unavailable","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}