can1357/oh-my-pi · error · ToolError
No page targets available on the attached browser
Error message
No page targets available on the attached browser
What it means
When attaching to an Electron browser, pickElectronTarget enumerates page targets and falls back to browser.pages(). If both lists are empty there is no page (webContents of type page) to attach to, so it throws ToolError("No page targets available on the attached browser"). The tool cannot proceed without at least one page target.
Source
Thrown at packages/coding-agent/src/tools/browser/attach.ts:206
*/
export async function pickElectronTarget(
browser: Browser,
options: { matcher?: string; preferVisible?: boolean } = {},
): Promise<Page> {
const discoveredPages = await Promise.all(
browser.targets().map(async target => {
if (String(target.type()) !== "page") return null;
return await target.page().catch(() => null);
}),
);
const usablePages = discoveredPages.filter((page): page is Page => page !== null);
if (usablePages.length > 0) {
return pickPageFromList(usablePages, options);
}
const fallbackPages = await browser.pages();
if (!fallbackPages.length) {
throw new ToolError("No page targets available on the attached browser");
}
return pickPageFromList(fallbackPages, options);
}
async function enrichPages(pages: Page[]): Promise<Array<{ page: Page; url: string; title: string }>> {
return await Promise.all(
pages.map(async page => ({
page,
url: page.url(),
title: ((await page.title().catch(() => "")) ?? "").trim(),
})),
);
}
async function pickPageFromList(pages: Page[], options: { matcher?: string; preferVisible?: boolean }): Promise<Page> {
const enriched = await enrichPages(pages);
if (options.matcher) {
const needle = options.matcher.toLowerCase();View on GitHub (pinned to 9690622007)
Solutions
- Ensure the Electron app has at least one open window before attaching
- Retry attach after the app finishes launching (poll for targets)
- Start the app with a window (do not use windowless/headless launch)
- Verify the CDP endpoint belongs to the actual app process, not a helper
- Relaunch the app with remote debugging enabled and a visible window
Example fix
// before
const tab = await attachElectron({ cdpUrl }); // app has no windows yet
// after
await waitForCondition(() => electronHasWindow()); // app created its window
const tab = await attachElectron({ cdpUrl }); Defensive patterns
Strategy: retry
Validate before calling
const targets = await fetch(`${cdpUrl}/json/list`).then(r => r.json());
const pages = targets.filter(t => t.type === "page");
if (!pages.length) throw new Error("wait for the Electron app to open a window before attaching"); Try / catch
try {
const tab = await attachElectron(opts);
} catch (e) {
if (e instanceof ToolError && e.message === "No page targets available on the attached browser") {
await Bun.sleep(1000); // app still launching; retry
return attachWithRetry(opts, attemptsLeft - 1);
}
throw e;
} Prevention
- Attach only after the app has created its first window
- Launch Electron with a visible window (not headless/windowless)
- Confirm the CDP port belongs to the app process, not a helper child
- Poll /json/list for type==page targets before attaching
When it happens
Trigger: Attaching to an Electron app that has no open BrowserWindows with page webContents; app still booting before its first window is created; all windows closed before attach; targets filtered out by the usable-page skip pattern leaving zero fallback pages.
Common situations: Attaching during Electron app startup before window creation; headless/service Electron processes without UI windows; windows closed by the app after launch; attaching to the wrong process (main/utility worker instead of the renderer host).
Related errors
- Timed out waiting for CDP endpoint ${cdpUrl}${lastStatus !==
- No page target matched ${JSON.stringify(options.matcher)}. A
- browser app.cdp_url must be the HTTP CDP discovery endpoint
- autoStarted ? `omp browser relay is serving at ${cdpUrl} but
- Failed to attach to ${path.basename(exe)} on ${cdpUrl}: ${(e
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/897c73cdf416939a.
Report an issue: GitHub.