Mintplex-Labs/anything-llm · error

No browser pages open.

Error message

No browser pages open.

What it means

cdp-input sibling of cdp-eval's page check: after Target.getTargets, pages are filtered to type 'page' excluding chrome:// and devtools:// URLs; if none remain, input injection has no target and the helper aborts with this error. The connection and WS handshake succeeded — the browser simply exposes no regular web page to attach to.

Solutions

  1. Navigate to or open a real http/https page, then retry the input command
  2. Add a small retry/delay right after browser launch until /json/list shows a page-type target with a non-chrome:// URL
  3. Set the agent's launch URL to a real page so a valid target always exists at startup
  4. Reopen crashed tabs (chrome://restore is filtered too — navigate explicitly) before injecting input

Example fix

# before
chromium --remote-debugging-port=9222 --user-data-dir=/tmp/oc-chrome &
node cdp-input.js click 100 200      # NTP only -> error
# after: launch straight into a page
chromium --remote-debugging-port=9222 --user-data-dir=/tmp/oc-chrome https://example.com &
node cdp-input.js click 100 200
Defensive patterns

Strategy: validation

Validate before calling

async function hasAttachablePage() {
  const targets = await (await fetch('http://127.0.0.1:9222/json/list')).json();
  return targets.some((t) => t.type === 'page' && !t.url.startsWith('chrome://') && !t.url.startsWith('devtools://'));
}

Try / catch

try { await sendInput('click', x, y); } catch (e) { if (/No browser pages open/.test(e.message)) { await openPage('https://example.com'); await sendInput('click', x, y); } else throw e; }

Prevention

When it happens

Trigger: Attempting click/type/key immediately after launching Chromium whose only tab is the new-tab page; the user (or page JS) closed all regular tabs; every open tab is a chrome:// internal page.

Common situations: Startup race where input is dispatched before the agent's start page finishes opening; kiosk/new-profile Chromium instances sitting on NTP; sessions where the page crashed and Chrome shows the sad-tab chrome://crash page.

Related errors


AI-assisted analysis of Mintplex-Labs/anything-llm@3aec848f28 (2026-08-18). Data as JSON: /api/errors/a460604ffbf9305c. Report an issue: GitHub.

Appendix: source

Thrown at open-computer/services/interface-service/utils/cdp-input.js:92

  const versionRaw = await httpGet("http://127.0.0.1:9222/json/version");
  const version = JSON.parse(versionRaw);
  const browserWsUrl = version.webSocketDebuggerUrl;
  if (!browserWsUrl) throw new Error("No webSocketDebuggerUrl — is Chromium running?");

  const ws = await new Promise((resolve, reject) => {
    const socket = new WebSocket(browserWsUrl);
    const t = setTimeout(() => reject(new Error("WS connect timeout")), 5000);
    socket.on("open", () => { clearTimeout(t); resolve(socket); });
    socket.on("error", (err) => { clearTimeout(t); reject(err); });
  });

  try {
    // Find target page
    const { targetInfos } = await cdpSend(ws, "Target.getTargets");
    const pages = targetInfos.filter(
      (t) => t.type === "page" && !t.url.startsWith("chrome://") && !t.url.startsWith("devtools://")
    );
    if (pages.length === 0) throw new Error("No browser pages open.");

    // Determine target URL filter (always last arg if it doesn't look like a coordinate/text)
    let targetUrl = "";
    if (action === "click") {
      targetUrl = process.argv[5] || "";
    } else if (action === "type") {
      targetUrl = process.argv[4] || "";
    } else if (action === "key") {
      targetUrl = process.argv[4] || "";
    }

    let target = pages[pages.length - 1];
    if (targetUrl) {
      const match = pages.find(
        (p) => p.url.includes(targetUrl) || p.title.toLowerCase().includes(targetUrl.toLowerCase())
      );
      if (!match) {
        const openTabs = pages.map((p) => `- ${p.title} ${p.url}`).join("\n");

View on GitHub (pinned to 3aec848f28)