{"record":{"id":"5bc213617b552232","repo":"can1357/oh-my-pi","slug":"browser-is-not-connected","errorCode":null,"errorMessage":"Browser is not connected","messagePattern":"Browser is not connected","errorType":"exception","errorClass":"ToolError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/tools/browser/tab-worker.ts","lineNumber":1134,"sourceCode":"\t\t\t\t\ttimeout: payload.timeoutMs,\n\t\t\t\t});\n\t\t\t}\n\t\t\tthis.#targetId = await targetIdForPage(this.#page);\n\t\t\tthis.#transport.send({ type: \"ready\", info: await this.#currentReadyInfo() });\n\t\t} catch (error) {\n\t\t\t// A failed headless init leaves the worker's page orphaned in the shared\n\t\t\t// browser (the supervisor retries with a fresh worker), so close it before\n\t\t\t// reporting. Attach mode adopts an existing target — never close it.\n\t\t\tconst page = this.#page;\n\t\t\tif (payload.mode === \"headless\" && page && !page.isClosed()) {\n\t\t\t\tawait page.close().catch(() => undefined);\n\t\t\t}\n\t\t\tthis.#transport.send({ type: \"init-failed\", error: errorPayload(error) });\n\t\t}\n\t}\n\n\tasync #findAttachedTarget(targetId: string): Promise<Target> {\n\t\tif (!this.#browser) throw new ToolError(\"Browser is not connected\");\n\t\tfor (const target of this.#browser.targets()) {\n\t\t\tif ((await targetIdForTarget(target).catch(() => \"\")) !== targetId) continue;\n\t\t\treturn target;\n\t\t}\n\t\tthrow new ToolError(`Target ${targetId} is no longer available on the attached browser`);\n\t}\n\n\t/**\n\t * Tell the omp browser relay this worker drives the adopted page, so the\n\t * relay adds it to the per-window \"omp\" tab group. Best-effort: plain CDP\n\t * backends (real Chrome, cmux) reject the relay-private method.\n\t */\n\tasync #claimRelayTarget(page: Page): Promise<void> {\n\t\tlet session: CDPSession | undefined;\n\t\ttry {\n\t\t\tsession = await page.createCDPSession();\n\t\t\t// Puppeteer's protocol map cannot express the relay-private method; the\n\t\t\t// send signature is otherwise identical.","sourceCodeStart":1116,"sourceCodeEnd":1152,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/tools/browser/tab-worker.ts#L1116-L1152","documentation":"#findAttachedTarget requires an active browser connection (`this.#browser`); if the worker's browser instance is disconnected or was never connected, it throws this ToolError instead of attempting a lookup. It is a precondition failure for any per-target operation.","triggerScenarios":"Any operation that resolves a targetId while the CDP connection is down: browser process exited/crashed, disconnect event fired but worker not reconnected, or an operation dispatched to the worker before `connect` completed.","commonSituations":"Browser closed by the user or OOM-killed mid-session; network drop to a remote browser; race where the tab operation arrives during browser shutdown/reconnect; worker reused after a previous teardown.","solutions":["Check/reestablish the browser connection before dispatching tab operations (reconnect then retry)","Verify the browser process is still running (check for crash or manual close)","Ensure connect() is awaited before issuing any tab commands","If reconnect is not possible, restart the browser session and re-acquire target IDs"],"exampleFix":"// before\nawait worker.runInTab(targetId, code); // throws if browser dropped\n// after\nif (!worker.isConnected) await worker.connect();\nawait worker.runInTab(targetId, code);","handlingStrategy":"validation","validationCode":"if (!worker.isConnected) {\n  await worker.connect(); // or surface a clear 'browser offline' state\n}","typeGuard":"function browserReady(w: { isConnected: boolean }): boolean {\n  return w.isConnected;\n}","tryCatchPattern":"try {\n  await worker.runInTab(targetId, code);\n} catch (err) {\n  if (err instanceof ToolError && err.message === 'Browser is not connected') {\n    await reconnectBrowser();\n    return worker.runInTab(targetId, code);\n  }\n  throw err;\n}","preventionTips":["Await connect() before any tab operation","Listen for disconnect events and pause/queue operations until reconnected","Health-check the browser process before long automation batches","Avoid issuing tab commands during shutdown/teardown sequences"],"tags":["browser","connection","cdp","lifecycle"],"backgroundTag":"browser-not-connected","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}