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

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.

Source

Thrown at packages/coding-agent/src/tools/browser/tab-supervisor.ts:1051

}

function expandBrowserScreenshotDir(session: ToolSession): string | undefined {
	const value = session.settings.get("browser.screenshotDir") as string | undefined;
	return value ? expandPath(value) : undefined;
}

async function targetIdForPage(page: Page): Promise<string> {
	return await targetIdForTarget(page.target());
}

async function targetIdForTarget(target: Target): Promise<string> {
	const raw = target as unknown as { _targetId?: unknown };
	if (typeof raw._targetId === "string") return raw._targetId;
	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);
	}
}

function errorFromPayload(payload: RunErrorPayload): Error {
	const error = payload.recoverTab
		? new RecoverableWorkerError(payload.message)
		: payload.isAbort
			? new ToolAbortError()
			: payload.isToolError
				? new ToolError(payload.message)
				: new Error(payload.message);
	error.name = payload.name;
	if (payload.stack) error.stack = payload.stack;
	return error;
}

View on GitHub (pinned to 9690622007)

Solutions

  1. 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.
  2. Check the puppeteer version: if `_targetId` was removed/renamed upstream, upgrade or pin puppeteer so the fast path in tab-supervisor works.
  3. Filter targets before resolving ids (skip `target.type() !== 'page'` targets) so CDP is only queried for real page targets.
  4. Wrap the call in try/catch and treat it as 'target gone': remove the tab from supervision instead of failing the whole tool call.

Example fix

// before
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");
// after
const info = (await session.send("Target.getTargetInfo").catch(() => undefined)) as
  | { targetInfo?: { targetId?: string } }
  | undefined;
if (info?.targetInfo?.targetId) return info.targetInfo.targetId;
return null; // caller treats null as 'target vanished' and re-lists targets
Defensive patterns

Strategy: try-catch

Validate before calling

// before calling
const target = browser.targets().find(t => t.type() === "page");
if (!target) throw new Error("no live page target available");

Try / catch

try {
  const id = await resolveTargetId(target);
} catch (err) {
  if (err instanceof ToolError && err.message.includes("Target id unavailable")) {
    return reenumerateTargets(); // target was closing
  }
  throw err;
}

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/55174df07d3b4860. Report an issue: GitHub.