karatelabs/karate · error · DriverException

timeout waiting for URL to contain

Error message

timeout waiting for URL to contain: ${expected}

What it means

CdpDriver.waitForUrl(expected, timeout) repeatedly reads the current page URL via CDP and returns it once it contains the expected substring; if the poll never matches within the timeout, a DriverException is thrown. This is the designated wait for client-side navigations / SPA route changes.

Solutions

  1. Increase the timeout to cover slow environments
  2. Print the actual URL (driver.getUrl()) after failure and correct the expected substring
  3. Wait for the condition that causes navigation (click/login response) to succeed before waiting on the URL
  4. Use waitForUrl with a stable path fragment rather than volatile query params

Example fix

// before
String url = driver.waitForUrl("http://localhost:8080/app?token=", Duration.ofSeconds(5));
// after
String url = driver.waitForUrl("/app", Duration.ofSeconds(15));
Defensive patterns

Strategy: try-catch

Validate before calling

String current = driver.getUrl();
if (current != null && current.contains("/app")) { /* already there, skip wait */ }

Try / catch

try {
    String url = driver.waitForUrl("/dashboard", Duration.ofSeconds(20));
} catch (DriverException e) {
    logger.error("URL wait failed; actual={}, expected-contains={}", driver.getUrl(), "/dashboard");
    throw e;
}

Prevention

When it happens

Trigger: driver.waitForUrl("/dashboard", Duration.ofSeconds(10)) when navigation did not happen, happened to a different URL, or took longer than the timeout; expected substring spelled differently from the actual URL (query params, hash, trailing slash).

Common situations: Login failed so the app stayed on the login page; SPA router redirected to an error route; redirect chain exceeded the wait budget on slow CI; expected substring includes a host while the URL compared is a path, or vice versa.

Understand the failure class

Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.

Related errors


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

Appendix: source

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

    }

    /**
     * Wait for URL to contain expected string.
     */
    public String waitForUrl(String expected) {
        return waitForUrl(expected, options.getTimeoutDuration());
    }

    /**
     * Wait for URL to contain expected string with custom timeout.
     */
    public String waitForUrl(String expected, Duration timeout) {
        String found = pollFor(timeout.toMillis(), options.getRetryInterval(), () -> {
            String url = getUrl();
            return url != null && url.contains(expected) ? url : null;
        });
        if (found == null) {
            throw new DriverException("timeout waiting for URL to contain: " + expected);
        }
        return found;
    }

    /**
     * Wait until a JavaScript expression on an element evaluates to truthy.
     * The element is available as '_' in the expression.
     */
    public Element waitUntil(String locator, String expression) {
        return waitUntil(locator, expression, options.getTimeoutDuration());
    }

    /**
     * Wait until a JavaScript expression on an element evaluates to truthy.
     */
    public Element waitUntil(String locator, String expression, Duration timeout) {
        Element found = pollFor(timeout.toMillis(), options.getRetryInterval(),
                () -> exists(locator) && Terms.isTruthy(script(locator, expression))

View on GitHub (pinned to a22eb90246)