{"record":{"id":"55174df07d3b4860","repo":"can1357/oh-my-pi","slug":"target-id-unavailable-from-cdp-target-info","errorCode":null,"errorMessage":"Target id unavailable from CDP target info","messagePattern":"Target id unavailable from CDP target info","errorType":"exception","errorClass":"ToolError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/tools/browser/tab-supervisor.ts","lineNumber":1051,"sourceCode":"}\n\nfunction expandBrowserScreenshotDir(session: ToolSession): string | undefined {\n\tconst value = session.settings.get(\"browser.screenshotDir\") as string | undefined;\n\treturn value ? expandPath(value) : undefined;\n}\n\nasync function targetIdForPage(page: Page): Promise<string> {\n\treturn await targetIdForTarget(page.target());\n}\n\nasync function targetIdForTarget(target: Target): Promise<string> {\n\tconst raw = target as unknown as { _targetId?: unknown };\n\tif (typeof raw._targetId === \"string\") return raw._targetId;\n\tconst session = await target.createCDPSession();\n\ttry {\n\t\tconst info = (await session.send(\"Target.getTargetInfo\")) as { targetInfo?: { targetId?: string } };\n\t\tif (info.targetInfo?.targetId) return info.targetInfo.targetId;\n\t\tthrow new ToolError(\"Target id unavailable from CDP target info\");\n\t} finally {\n\t\tawait session.detach().catch(() => undefined);\n\t}\n}\n\nfunction errorFromPayload(payload: RunErrorPayload): Error {\n\tconst error = payload.recoverTab\n\t\t? new RecoverableWorkerError(payload.message)\n\t\t: payload.isAbort\n\t\t\t? new ToolAbortError()\n\t\t\t: payload.isToolError\n\t\t\t\t? new ToolError(payload.message)\n\t\t\t\t: new Error(payload.message);\n\terror.name = payload.name;\n\tif (payload.stack) error.stack = payload.stack;\n\treturn error;\n}\n","sourceCodeStart":1033,"sourceCodeEnd":1069,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/tools/browser/tab-supervisor.ts#L1033-L1069","documentation":"The tab-supervisor resolves a Puppeteer Target's id by first reading the private `_targetId` field, then falling back to opening a temporary CDP session and calling `Target.getTargetInfo`. This ToolError is thrown when the CDP response arrives but contains no `targetInfo.targetId`, meaning the browser could not identify the target.","triggerScenarios":"Called on a Target whose CDP session connects but returns an empty/malformed `Target.getTargetInfo` response — typically a target that is closing, already closed, or of a type that never exposes a page target id (e.g. a service-worker or browser-level target).","commonSituations":"Racing a tab close while tab bookkeeping runs; connecting to a flaky/remote Chromium via CDP that drops target info; puppeteer internals changed so `_targetId` is absent and the CDP fallback hits an already-detached target.","solutions":["Retry the operation after a short delay — the target is likely closing; re-enumerate targets via browser.targets() and pick one that still reports a page.","Check the puppeteer version: if `_targetId` was removed/renamed upstream, upgrade or pin puppeteer so the fast path in tab-supervisor works.","Filter targets before resolving ids (skip `target.type() !== 'page'` targets) so CDP is only queried for real page targets.","Wrap the call in try/catch and treat it as 'target gone': remove the tab from supervision instead of failing the whole tool call."],"exampleFix":"// before\nconst info = (await session.send(\"Target.getTargetInfo\")) as { targetInfo?: { targetId?: string } };\nif (info.targetInfo?.targetId) return info.targetInfo.targetId;\nthrow new ToolError(\"Target id unavailable from CDP target info\");\n// after\nconst info = (await session.send(\"Target.getTargetInfo\").catch(() => undefined)) as\n  | { targetInfo?: { targetId?: string } }\n  | undefined;\nif (info?.targetInfo?.targetId) return info.targetInfo.targetId;\nreturn null; // caller treats null as 'target vanished' and re-lists targets","handlingStrategy":"try-catch","validationCode":"// before calling\nconst target = browser.targets().find(t => t.type() === \"page\");\nif (!target) throw new Error(\"no live page target available\");","typeGuard":null,"tryCatchPattern":"try {\n  const id = await resolveTargetId(target);\n} catch (err) {\n  if (err instanceof ToolError && err.message.includes(\"Target id unavailable\")) {\n    return reenumerateTargets(); // target was closing\n  }\n  throw err;\n}","preventionTips":["Only resolve ids for targets with type() === 'page'","Avoid resolving ids during teardown/navigation races; add small delays or retry","Keep puppeteer updated so the _targetId fast path works"],"tags":["cdp","puppeteer","browser-tab","target-id"],"backgroundTag":"cdp-target-info-unavailable","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}