karatelabs/karate · warning
Page.navigate timed out, retrying
Error message
Page.navigate timed out, retrying ({}/{}): {} What it means
Karate's CDP driver retries Page.navigate when the browser fails to answer within the CDP timeout, logging this warning between attempts. The message reports attempt progress ({}/{}), the retry budget, and the target URL. It is a warning, not a thrown error; a RuntimeException is only rethrown after the final attempt also times out.
Solutions
- Increase the CDP timeout (e.g. karate.configure('webdriverTimeout'/'timeout') or the driver timeout config) so navigation has more headroom.
- Retry the driver.get()/loadUrl call; transient attempts often succeed on the second try.
- Verify the target URL is reachable from the test host (curl it) and check DNS/proxy settings.
- Reduce load on the browser/CI runner (fewer parallel Chrome instances) and ensure adequate CPU/memory.
Example fix
// before
karate.configure('timeout', 10000);
// after
karate.configure('timeout', 30000); // more headroom for slow Page.navigate on loaded CI Defensive patterns
Strategy: retry
Validate before calling
// check reachability before navigating
boolean ok = java.net.InetAddress.getByName("example.com").isReachable(3000); Try / catch
try { driver.get(url); } catch (RuntimeException e) { if (e.getMessage().contains("CDP timeout for: Page.navigate")) { driver.get(url); } else { throw e; } } Prevention
- Configure a generous page/CDP timeout for CI
- Check URL reachability before navigation
- Limit parallel Chrome instances on shared runners
- Retry flaky navigations at the test level
When it happens
Trigger: driver.loadUrl / driver.get(url) where the CDP Page.navigate command exceeds the CDP timeout, e.getMessage() contains 'CDP timeout for: Page.navigate', and attempt < navAttempts - 1 so a retry is still available.
Common situations: Slow or overloaded CI machines, remote/headless Chrome under load, very large pages or slow redirects, network latency to an external URL, or a CDP websocket momentarily stalled during navigation.
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.
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- page load timeout after
- Page.navigate returned ERR_ABORTED, retrying
- retry FAILED after attempts: |
- retry failed after attempts:
- CDP timeout for
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/7d18e82bc5465860.
Report an issue: GitHub.
Appendix: source
Thrown at karate-core/src/main/java/io/karatelabs/driver/cdp/CdpDriver.java:1303
// (element-not-found, waitUntil timeouts, value mismatches). A deliberate
// abort re-aborts on every attempt, so after the bounded retries we accept
// the retention (history.feature's 204 test still passes); a spurious
// abort commits on a retry and the scenario gets the document it asked for.
// (A beforeunload prompt is auto-accepted in the dialog handler above, so the
// timeout retry is for genuine transient timeouts, not the leave-page case.)
int navAttempts = 3;
CdpResponse navResponse = null;
boolean aborted = false;
for (int attempt = 0; attempt < navAttempts; attempt++) {
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 errorView on GitHub (pinned to a22eb90246)