{"record":{"id":"e3dbeb263658295f","repo":"karatelabs/karate","slug":"page-load-timeout-after-ms-ms-url-url-strategy-strategy","errorCode":null,"errorMessage":"page load timeout after {ms}ms - url: {url}, strategy: {strategy}, domContentEventFired: {bool}, framesStillLoading: {bool}, mainFrameId: {id}, expectedLoaderId: {id}, supersededLoaderId: {id}, committedLoaderId: {id}, domContentLoaderId: {id}, readyState: {state}, jsExec: {state}, cdpOpen: {bool}","messagePattern":"page load timeout after (.+?)ms - url: (.+?), strategy: (.+?), domContentEventFired: (.+?), framesStillLoading: (.+?), mainFrameId: (.+?), expectedLoaderId: (.+?), supersededLoaderId: (.+?), committedLoaderId: (.+?), domContentLoaderId: (.+?), readyState: (.+?), jsExec: (.+?), cdpOpen: (.+?)","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"karate-core/src/main/java/io/karatelabs/driver/cdp/CdpDriver.java","lineNumber":1441,"sourceCode":"                // timeout (or exceptional completion): fall through and re-check\n            }\n        }\n\n        // Build diagnostic message with comprehensive state info\n        String url = pendingNavigationUrl != null ? pendingNavigationUrl : \"(unknown)\";\n        String readyStateInfo = getReadyStateForDiagnostic();\n        String jsExecInfo = getJsExecStateForDiagnostic();\n        String diagnostic = String.format(\n                \"page load timeout after %dms - url: %s, strategy: %s, \" +\n                \"domContentEventFired: %s, framesStillLoading: %s, mainFrameId: %s, \" +\n                \"expectedLoaderId: %s, supersededLoaderId: %s, committedLoaderId: %s, domContentLoaderId: %s, \" +\n                \"readyState: %s, jsExec: %s, cdpOpen: %s\",\n                timeout.toMillis(), url, strategy,\n                domContentEventFired, framesStillLoading, mainFrameId,\n                expectedLoaderId, supersededLoaderId, committedLoaderId, domContentLoaderId,\n                readyStateInfo, jsExecInfo, cdp.isOpen());\n        logger.warn(diagnostic);\n        throw new RuntimeException(diagnostic);\n    }\n\n    /**\n     * Verify that JS execution works in the context script() will actually use.\n     * <p>\n     * The page is only truly \"loaded\" once the main frame's default execution context\n     * is live - that is the single thing the readiness future tracks. We await it\n     * briefly (it is usually already complete; during a navigation swap it settles in\n     * milliseconds) and probe THAT context.\n     * <p>\n     * Crucially, an <i>error</i> from the explicit-context probe is NOT taken as \"JS not\n     * ready\": {@link #mainContextReady} can hand out a contextId that a loader\n     * replacement has already torn down when the matching executionContextsCleared was\n     * never delivered (routine under CI load). The stale id then errors forever and, on\n     * a fully-loaded page, wedges waitForPageLoad() to a 30s timeout — observed in CI as\n     * \"page load complete but JS context not ready yet\" while the timeout diagnostic\n     * reports {@code jsExec: ok} (it probes the default context). So on an explicit-\n     * context error we re-probe the default context: this is a liveness check","sourceCodeStart":1423,"sourceCodeEnd":1459,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-core/src/main/java/io/karatelabs/driver/cdp/CdpDriver.java#L1423-L1459","documentation":"Karate waited for a page load (navigation) until the configured timeout and the load did not complete. The message embeds a rich diagnostic: whether domContentEventFired fired, frames still loading, the main frame id, and the progression of loader ids (expected/superseded/committed/domContent) plus document readyState, JS-executability and CDP connection state, to pinpoint where loading stalled.","triggerScenarios":"driver.setUrl(url) or navigation with waitUntil strategy where, after the timeout duration, DOMContentLoaded never fired, or frames remained in loading state, or the loader chain shows a superseded navigation, or the document never reached the expected readyState.","commonSituations":"Slow pages behind corporate proxies/VPN; ad-blockers or CSP blocking critical resources; pages that never finish loading (long-polling, streaming media); misjudged waitUntil strategy or too-low driver timeout config; servers hanging on a subresource.","solutions":["Increase the driver timeout (e.g. configure options.timeout or karate driver config) so slow pages can finish loading","Change the waitUntil strategy (e.g. from 'load' to 'domcontentloaded') if a late subresource blocks the load event","Open the diagnostic fields: framesStillLoading=true points at an iframe/hung subresource; committedLoaderId null means navigation never committed (check network/DNS/TLS)","Check the page manually in a browser at the same network path to identify blocking resources"],"exampleFix":"// before\nDriverOptions: { type:'chromium', timeout: 30000, waitForLoad:'load' }\n// after\nDriverOptions: { type:'chromium', timeout: 90000, waitForLoad:'domcontentloaded' }","handlingStrategy":"try-catch","validationCode":"// pre-check reachability before navigation\nHttp.Response r = Http.forUrl(url).header(\"Connection\",\"close\").get();\nif (r.getStatus() >= 400) throw new IllegalStateException(\"target url unhealthy: \" + r.getStatus());","typeGuard":null,"tryCatchPattern":"try { driver.setUrl(url); } catch (RuntimeException e) { if (e.getMessage().startsWith(\"page load timeout\")) { logger.warn(\"load stalled: {}\", e.getMessage()); driver.setUrl(url); // one retry  } else throw e; }","preventionTips":["Size the driver timeout to the slowest environment, not local dev","Prefer domcontentloaded strategy for pages with long-loading subresources","Block known-slow third-party domains via proxy or hosts entries","Read the diagnostic fields (framesStillLoading, committedLoaderId) to target the real stall cause"],"tags":["cdp","page-load","timeout","navigation"],"backgroundTag":"request-timeout","analyzedSha":"a22eb90246d958d15a47bf436693d0121ad2812d","analyzedAt":"2026-09-12T09:01:00.220Z","contentChangedAt":"2026-09-12T09:01:00.220Z","schemaVersion":2},"datasetVersion":"2026-09-16T19:17:19.609Z"}