can1357/oh-my-pi · error · ToolError
Target id unavailable from CDP target info
Error message
Target id unavailable from CDP target info
What it means
Same failure family as the tab-supervisor variant: when resolving a Target's id, the fast path (`privateTargetId`) misses, so a temporary CDP session issues `Target.getTargetInfo`. If the response lacks `targetInfo.targetId`, this ToolError is thrown and the session is detached in `finally`.
Source
Thrown at packages/coding-agent/src/tools/browser/tab-worker.ts:697
const err = new Ctor(payload.message);
if (payload.name) err.name = payload.name;
if (payload.stack) err.stack = payload.stack;
return err;
}
function privateTargetId(target: Target): string | undefined {
const raw = target as unknown as { _targetId?: unknown };
return typeof raw._targetId === "string" ? raw._targetId : undefined;
}
async function targetIdForTarget(target: Target): Promise<string> {
const fastTargetId = privateTargetId(target);
if (fastTargetId) return fastTargetId;
const session = await target.createCDPSession();
try {
const info = (await session.send("Target.getTargetInfo")) as { targetInfo?: { targetId?: string } };
if (info.targetInfo?.targetId) return info.targetInfo.targetId;
throw new ToolError("Target id unavailable from CDP target info");
} finally {
await session.detach().catch(() => undefined);
}
}
async function targetIdForPage(page: Page): Promise<string> {
return await targetIdForTarget(page.target());
}
async function createTrackedHeadlessPage(browser: Browser, reportTarget: (targetId: string) => void): Promise<Page> {
const session = await browser.target().createCDPSession();
let targetId: string;
try {
({ targetId } = await session.send("Target.createTarget", { url: "about:blank" }));
reportTarget(targetId);
} finally {
await session.detach().catch(() => undefined);
}View on GitHub (pinned to 9690622007)
Solutions
- Skip non-page targets before resolving ids (`target.type() === "page"` check).
- Treat the error as 'target is gone': drop the tab from tracking and re-enumerate `browser.targets()`.
- Upgrade/pin puppeteer so the private `_targetId` fast path is available again.
- Retry the lookup after a short delay if the target is expected to settle.
Example fix
// before
const id = targetIdForPage(page); // throws if CDP info is empty
// after
try {
const id = targetIdForPage(page);
} catch {
await supervisor.forgetTab(page); // target vanished; re-list tabs instead of failing
} Defensive patterns
Strategy: fallback
Validate before calling
const candidates = browser.targets().filter(t => t.type() === "page");
if (candidates.length === 0) throw new Error("no page targets attached"); Try / catch
try {
const id = await targetIdForPage(page);
} catch {
const id = (await browser.pages()).find(p => p === page) ? undefined : null;
// fall back to re-listing pages and matching by URL
} Prevention
- Skip non-page targets before id resolution
- Treat id-resolution failures as 'target gone' and re-enumerate
- Pin puppeteer to a version where Target._targetId exists
When it happens
Trigger: `targetIdForTarget` / `targetIdForPage` / `#findAttachedTarget` invoked on a target that is detaching or closing — the CDP round-trip succeeds structurally but carries no target id.
Common situations: Tab closed concurrently with bookkeeping; service-worker or extension-background targets enumerated by mistake; puppeteer upgrade removing the `_targetId` fast path so every lookup hits the fragile CDP fallback.
Related errors
- Target id unavailable from CDP target info
- Connected to ${cdpUrl} but puppeteer.connect failed: ${(err
- Created headless target ${targetId} did not expose a page
- Target ${payload.targetId} is no longer available on the att
- Target ${targetId} is no longer available on the attached br
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/033520b2d5e788f1.
Report an issue: GitHub.