karatelabs/karate · warning

Page.navigate returned ERR_ABORTED, retrying

Error message

Page.navigate returned ERR_ABORTED, retrying ({}/{}): {}

What it means

When the browser responds to Page.navigate with errorText 'net::ERR_ABORTED', the CDP driver logs this warning and sleeps 150ms before retrying, letting an in-flight or racing navigation (e.g. a pooled-reset about:blank) settle. ERR_ABORTED means the navigation was cancelled by the browser rather than committed. If every attempt is aborted, the driver instead treats it as a deliberate download/204/window.stop and keeps the current document.

Solutions

  1. Expect the abort: for download/204 targets use driver.download or HTTP steps instead of driver.get().
  2. Retry the navigation after a short delay; the 150ms settle often resolves the race.
  3. Check for pooled-driver about:blank resets colliding with your navigation (serialize driver usage per scenario).
  4. Inspect the page for window.stop() calls or meta refresh/JS that immediately cancels navigation.

Example fix

// before
driver.get('https://example.com/report.csv'); // triggers download, ERR_ABORTED
// after
driver.http('https://example.com/report.csv').download(); // or use karate HTTP for non-document responses
Defensive patterns

Strategy: retry

Validate before calling

// detect download/204 targets before driver.get()
var head = karate.http(url).method('head'); boolean isDocument = head.status < 300 && !head.header('content-disposition');

Prevention

When it happens

Trigger: driver.get()/loadUrl() where navResponse.getResultAsString("errorText") equals 'net::ERR_ABORTED' and attempt < navAttempts - 1.

Common situations: Navigating to URLs that trigger a download instead of a document, HTTP 204/205 responses, in-page window.stop(), or a race where the driver resets the page to about:blank (pooled drivers) while the navigation starts.

Related errors


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

Appendix: source

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

            try {
                navResponse = cdp.method("Page.navigate")
                        .param("url", url)
                        .send();
            } catch (RuntimeException e) {
                boolean transientNavTimeout = e.getMessage() != null
                        && e.getMessage().contains("CDP timeout for: Page.navigate");
                if (transientNavTimeout && attempt < navAttempts - 1) {
                    logger.warn("Page.navigate timed out, retrying ({}/{}): {}", attempt + 1, navAttempts - 1, url);
                    continue;
                }
                throw e;
            }
            aborted = "net::ERR_ABORTED".equals(navResponse.getResultAsString("errorText"));
            if (!aborted) {
                break; // committed, an error page under the same loader, or a normal response
            }
            if (attempt < navAttempts - 1) {
                logger.warn("Page.navigate returned ERR_ABORTED, retrying ({}/{}): {}", attempt + 1, navAttempts - 1, url);
                sleep(150); // let an in-flight/racing navigation (e.g. pooled-reset about:blank) settle
            }
        }

        // Every attempt aborted — a deliberate download / 204-205 / window.stop() that
        // retains the current document. The returned loader never commits, never fires
        // DOMContentLoaded, and a loader-bound wait for it could only end in a timeout,
        // so return with the page as-is (genuine load failures instead commit an error
        // page under the SAME loader, and the normal wait below handles those).
        if (aborted) {
            logger.warn("navigation aborted by browser, current document retained: {}", url);
            pendingNavigationUrl = null;
            return;
        }

        // data: and about: URLs commit locally and don't fire the normal load lifecycle,
        // so the full waitForPageLoad below would only ever time out on them. Returning
        // with no barrier at all is what let the pooled reset's about:blank still be in

View on GitHub (pinned to a22eb90246)