can1357/oh-my-pi · error · ToolError
Target ${targetId} is no longer available on the attached br
Error message
Target ${targetId} is no longer available on the attached browser What it means
#findAttachedTarget iterates `browser.targets()` comparing each target's id to the requested targetId; when no target matches, it throws that the target is no longer available. It is the authoritative 'this tab does not exist in the attached browser' error.
Source
Thrown at packages/coding-agent/src/tools/browser/tab-worker.ts:1139
} catch (error) {
// A failed headless init leaves the worker's page orphaned in the shared
// browser (the supervisor retries with a fresh worker), so close it before
// reporting. Attach mode adopts an existing target — never close it.
const page = this.#page;
if (payload.mode === "headless" && page && !page.isClosed()) {
await page.close().catch(() => undefined);
}
this.#transport.send({ type: "init-failed", error: errorPayload(error) });
}
}
async #findAttachedTarget(targetId: string): Promise<Target> {
if (!this.#browser) throw new ToolError("Browser is not connected");
for (const target of this.#browser.targets()) {
if ((await targetIdForTarget(target).catch(() => "")) !== targetId) continue;
return target;
}
throw new ToolError(`Target ${targetId} is no longer available on the attached browser`);
}
/**
* Tell the omp browser relay this worker drives the adopted page, so the
* relay adds it to the per-window "omp" tab group. Best-effort: plain CDP
* backends (real Chrome, cmux) reject the relay-private method.
*/
async #claimRelayTarget(page: Page): Promise<void> {
let session: CDPSession | undefined;
try {
session = await page.createCDPSession();
// Puppeteer's protocol map cannot express the relay-private method; the
// send signature is otherwise identical.
const raw = session as unknown as { send(method: string): Promise<unknown> };
await raw.send("OMP.claimTarget");
} catch {
// Not the omp relay; nothing to claim.
} finally {View on GitHub (pinned to 9690622007)
Solutions
- Re-list `browser.targets()` and select a currently valid targetId
- Reopen the target (open a new tab with the same URL) if the content is still needed
- Refresh cached target IDs after navigation or reconnect events
- Validate targetId against a fresh target list before each operation in long-running scripts
Example fix
// before await worker.runInTab(cachedTargetId, code); // after const live = await worker.listTargets(); const id = live.find(t => t.url === expectedUrl)?.id ?? (await worker.openTab(expectedUrl)).id; await worker.runInTab(id, code);
Defensive patterns
Strategy: validation
Validate before calling
const live = await worker.listTargets();
if (!live.some(t => t.id === targetId)) {
targetId = (await worker.openTab(url)).id;
} Type guard
function hasTarget(targets: {id:string}[], id: string): targets is {id:string}[] & {find(t: {id:string}): boolean} {
return targets.some(t => t.id === id);
} Try / catch
try {
await worker.runInTab(targetId, code);
} catch (err) {
if (err instanceof ToolError && err.message.includes('no longer available')) {
const fresh = await worker.openTab(url);
return worker.runInTab(fresh.id, code);
}
throw err;
} Prevention
- Resolve target IDs fresh from browser.targets() instead of caching them
- Refresh IDs after page navigations that can swap the underlying target
- Track browser 'targetdestroyed'-style events to drop dead IDs eagerly
- Validate the ID against a live listing before each operation in scripts that run long
When it happens
Trigger: Adopting/operating on a targetId that was closed, navigated away, or never existed in the currently attached browser; stale target IDs from a previous session or after a page transitioned to a different target type.
Common situations: Script holds target IDs across a browser restart; user closed the tab; SPA/page navigation replaced the target; ID typo or ID copied from a different browser instance.
Related errors
- Target ${payload.targetId} is no longer available on the att
- Connected to ${cdpUrl} but puppeteer.connect failed: ${(err
- Timed out waiting for CDP endpoint ${cdpUrl}${lastStatus !==
- No page targets available on the attached browser
- browser app.cdp_url must be the HTTP CDP discovery endpoint
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/ceb6e529f2c38bf0.
Report an issue: GitHub.