Mintplex-Labs/anything-llm · error · Error

No browser tab matching

Error message

No browser tab matching "${targetUrl}". Open tabs:
${openTabs}

What it means

Thrown by cdp-eval when a targetUrl filter argument was supplied but no open page matches: matching is substring 'url.includes(targetUrl)' OR case-insensitive 'title.includes(targetUrl)'. The error lists every open tab (title + URL) to make the mismatch obvious. The default without a filter is the most recently opened page, so this only fires when an explicit tab selector was passed.

Solutions

  1. Read the 'Open tabs:' list in the error and re-issue with a substring that actually appears in one of the listed URLs (URLs are the stable choice)
  2. If the tab was closed, re-open/navigate to the target URL first, then retry with the same filter
  3. Prefer a distinctive URL fragment (hostname+path piece) over titles, which change with page state
  4. Drop the filter entirely to act on the most recent tab when any tab is acceptable

Example fix

# before: filter no longer matches after a redirect
node cdp-eval.js 'console.log(1)' 'github.com/login'
# after: use the post-login URL fragment shown in 'Open tabs:'
node cdp-eval.js 'console.log(1)' 'github.com/dashboard'
Defensive patterns

Strategy: validation

Validate before calling

async function tabMatches(filter) {
  const targets = await (await fetch('http://127.0.0.1:9222/json/list')).json();
  const pages = targets.filter((t) => t.type === 'page' && !t.url.startsWith('chrome://') && !t.url.startsWith('devtools://'));
  return pages.some((p) => p.url.includes(filter) || p.title.toLowerCase().includes(filter.toLowerCase()));
}
if (filter && !(await tabMatches(filter))) { /* re-open the page or drop the filter */ }

Try / catch

try { await evalInPage(expr, filter); } catch (e) { if (/No browser tab matching/.test(e.message)) { /* e.message lists open tabs — pick a fresh substring from it and retry once */ } else throw e; }

Prevention

When it happens

Trigger: Invoking the eval helper with a URL/title fragment (e.g. 'github.com/myrepo') when no open tab contains that substring in URL or title; the tab was closed or navigated away between calls; typo/case mismatch in the URL fragment (URL match is case-sensitive, only title match lowercases); auth redirect changed the URL so the fragment no longer appears.

Common situations: Agent assumes a page is still open after a redirect or popup closed it; targeting by document title that changes dynamically (SPA title updates); passing a full title with different casing/emoji than the tab shows.

Related errors


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

Appendix: source

Thrown at open-computer/services/interface-service/utils/cdp-eval.js:94

    socket.on("open", () => { clearTimeout(t); resolve(socket); });
    socket.on("error", (err) => { clearTimeout(t); reject(err); });
  });

  try {
    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.");

    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");
        throw new Error(`No browser tab matching "${targetUrl}". Open tabs:\n${openTabs}`);
      }
      if (match) target = match;
    }

    const { sessionId } = await cdpSend(ws, "Target.attachToTarget", {
      targetId: target.targetId,
      flatten: true,
    });

    await cdpSend(ws, "Runtime.enable", {}, sessionId);

    const evalResult = await cdpSend(ws, "Runtime.evaluate", {
      expression: code,
      returnByValue: true,
      awaitPromise: true,
      userGesture: true,
    }, sessionId);

View on GitHub (pinned to 3aec848f28)