{"record":{"id":"de03a0b293edaa1c","repo":"can1357/oh-my-pi","slug":"created-headless-target-targetid-did-not-expose","errorCode":null,"errorMessage":"Created headless target ${targetId} did not expose a page","messagePattern":"Created headless target (.+?) did not expose a page","errorType":"exception","errorClass":"ToolError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/tools/browser/tab-worker.ts","lineNumber":723,"sourceCode":"}\n\nasync function createTrackedHeadlessPage(browser: Browser, reportTarget: (targetId: string) => void): Promise<Page> {\n\tconst session = await browser.target().createCDPSession();\n\tlet targetId: string;\n\ttry {\n\t\t({ targetId } = await session.send(\"Target.createTarget\", { url: \"about:blank\" }));\n\t\treportTarget(targetId);\n\t} finally {\n\t\tawait session.detach().catch(() => undefined);\n\t}\n\tconst existing = browser.targets().find(target => privateTargetId(target) === targetId);\n\tconst target =\n\t\texisting ??\n\t\t(await browser.waitForTarget(candidate => privateTargetId(candidate) === targetId, {\n\t\t\ttimeout: BROWSER_PROTOCOL_TIMEOUT_MS,\n\t\t}));\n\tconst page = await target.page();\n\tif (!page) throw new ToolError(`Created headless target ${targetId} did not expose a page`);\n\treturn page;\n}\n\nasync function collectObservationEntries(\n\tcore: WorkerCore,\n\tnode: SerializedAXNode,\n\tentries: ObservationEntry[],\n\toptions: { viewportOnly: boolean; includeAll: boolean },\n): Promise<void> {\n\tif (options.includeAll || isInteractiveNode(node)) {\n\t\tconst handle = await node.elementHandle();\n\t\tif (handle) {\n\t\t\tlet inViewport = true;\n\t\t\tif (options.viewportOnly) {\n\t\t\t\ttry {\n\t\t\t\t\tinViewport = await handle.isIntersectingViewport();\n\t\t\t\t} catch {\n\t\t\t\t\tinViewport = false;","sourceCodeStart":705,"sourceCodeEnd":741,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/tools/browser/tab-worker.ts#L705-L741","documentation":"createTrackedHeadlessPage creates a new headless tab via CDP, waits for the corresponding puppeteer Target (matched by its private target id), then asks for its Page object. If `target.page()` returns null/undefined — the target exists but is not a page or exposes no page — this ToolError is thrown.","triggerScenarios":"`Target.createTarget` created a target of a non-page type or a page target that detached before `target.page()` resolved; `waitForTarget` matched the right id but the page never attached.","commonSituations":"Chromium under heavy load during startup; headless browser crash mid-creation; CDP `createTarget` flags producing a tab-less target; racing browser shutdown in tests.","solutions":["Retry the tab creation — transient attach races usually succeed on a second attempt.","Verify the headless browser is healthy (not crashed) by checking `browser.isConnected()`; restart it if not.","Ensure `createTarget` is called with `url: \"about:blank\"` (or similar) so the target is a real page.","Catch and clean up: close the orphan targetId so the next attempt doesn't accumulate dead targets."],"exampleFix":"// before\nconst page = createTrackedHeadlessPage(browser, targetId);\n// after\nlet page;\ntry {\n  page = await createTrackedHeadlessPage(browser, targetId);\n} catch {\n  await cdpSend(\"Target.closeTarget\", { targetId }).catch(() => {});\n  page = await createTrackedHeadlessPage(browser, await cdpCreateTarget());\n}","handlingStrategy":"retry","validationCode":"if (!browser.isConnected()) throw new Error(\"headless browser disconnected; restart before creating tabs\");","typeGuard":null,"tryCatchPattern":"try {\n  const page = await createTrackedHeadlessPage(browser, targetId);\n} catch (err) {\n  if (err instanceof ToolError && err.message.includes(\"did not expose a page\")) {\n    await closeOrphanTarget(targetId);\n    return createTrackedHeadlessPage(browser, await newTargetId()); // one retry\n  }\n  throw err;\n}","preventionTips":["Create targets with an explicit url so they are real pages","Close orphan targets on failure so retries start clean","Check browser.isConnected() before creating tabs"],"tags":["headless","cdp","puppeteer","page-creation"],"backgroundTag":"headless-target-no-page","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}