karatelabs/karate · error · DriverException

no page found matching

Error message

no page found matching: ${titleOrUrl}

What it means

A page-switch helper (switchPage-style polling over CDP targets) exhausts its retry attempts without finding a page target whose title or URL contains the given substring, then throws this DriverException. Karate retries at a fast poll interval so freshly opened tabs are picked up, but if no matching target appears the wait is abandoned.

Solutions

  1. List current targets (getPages / Target.getTargets via devtools) and match the argument against actual titles/URLs
  2. Increase the switch timeout/retry config so slow popups are covered
  3. Ensure the action that opens the new tab actually executed (check for popup blockers)
  4. Pass a stable substring of the final URL (after redirects) rather than the initial about:blank or transient title

Example fix

// before
driver.switchPage("Reports Dashboard");
// after
logger.debug("pages={}", driver.getPages());
String url = (String) driver.script("window.location.href");
driver.switchPage(url.contains("reports") ? "reports" : "Reports Dashboard");
Defensive patterns

Strategy: retry

Validate before calling

List<String> pages = driver.getPages();
if (pages.isEmpty()) { throw new IllegalStateException("no page targets open"); }

Try / catch

try {
    driver.switchPage("Reports Dashboard");
} catch (DriverException e) {
    logger.error("no matching tab; open targets={}", driver.getPages());
    // one retry in case the popup was slow
    karate.call.sleep(1000);
    driver.switchPage("Reports");
}

Prevention

When it happens

Trigger: switchPage(titleOrUrl) (or the matching driver keyword) called with a substring that matches no open tab's title or URL — the tab never opened, closed before the switch, or the title/URL differs from the argument.

Common situations: window.open / target=_blank link never fired (popup blocked); new tab URL is an exact match only but the argument is a partial string from an older app version; tab closed by the app before the poll; typos or case-sensitivity in the substring.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12). Data as JSON: /api/errors/3690636ca99ab8c8. Report an issue: GitHub.

Appendix: source

Thrown at karate-core/src/main/java/io/karatelabs/driver/cdp/CdpDriver.java:3961

        // Retry the enumeration: Target.getTargets can transiently lag a freshly
        // opened/closed tab, or report a page whose url/title field is not yet
        // populated while it is still loading - especially under parallel load. A
        // single-shot lookup then spuriously throws "no page found" (observed flaky
        // on tab-switch under CI). Poll within the same budget as other auto-waits.
        int interval = fastPollInterval();
        int maxAttempts = fastPollAttempts();
        for (int attempt = 0; ; attempt++) {
            String targetId = findPageTarget(titleOrUrl);
            if (targetId != null) {
                activateTarget(targetId);
                return;
            }
            if (attempt >= maxAttempts) {
                break;
            }
            sleep(interval);
        }
        throw new DriverException("no page found matching: " + titleOrUrl);
    }

    /**
     * Find a page target whose title or URL contains the given substring, or null.
     */
    private String findPageTarget(String titleOrUrl) {
        for (Map<String, Object> target : pageTargets()) {
            String title = (String) target.get("title");
            String url = (String) target.get("url");
            if ((title != null && title.contains(titleOrUrl)) ||
                    (url != null && url.contains(titleOrUrl))) {
                return (String) target.get("targetId");
            }
        }
        return null;
    }

    /**

View on GitHub (pinned to a22eb90246)