{"record":{"id":"f95495b95ac74947","repo":"karatelabs/karate","slug":"main-frame-context-never-became-ready-after-attempts-falling","errorCode":null,"errorMessage":"main-frame context never became ready after {} attempts, falling back to default context: {}","messagePattern":"main-frame context never became ready after (.+?) attempts, falling back to default context: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"karate-core/src/main/java/io/karatelabs/driver/cdp/CdpDriver.java","lineNumber":1884,"sourceCode":"                // returns a misleading null instead of the main-frame value - the source\n                // of a rare CI flake (frame.feature \"Multiple switches\" reading\n                // window.mainValue as null under a slow context swap). Self-heal instead:\n                // give the replacement executionContextCreated more time via the retry\n                // loop, which re-awaits the readiness future on the next getFrameContext().\n                // Logged at WARN so a recurrence is visible in CI for the next investigation.\n                logger.warn(\"main-frame context not ready, retry {}/{}: {}\", attempt + 1, maxRetries, truncate(expression, 100));\n                sleep(transientInterval);\n                continue;\n            }\n            if (contextId != null) {\n                message.param(\"contextId\", contextId);\n            } else if (mainContextUnresolved) {\n                // Retries exhausted and the main context never registered - e.g. a\n                // download / 204 / aborted navigation that clears the context without a\n                // replacement. Degrade to CDP's default context as a last resort rather\n                // than hard-failing, matching the documented graceful-degradation intent,\n                // but log loudly so a recurrence stands out in CI logs.\n                logger.warn(\"main-frame context never became ready after {} attempts, falling back to default context: {}\", maxRetries, truncate(expression, 100));\n            }\n\n            CdpResponse response;\n            try {\n                response = message.send();\n            } catch (DialogOpenedException e) {\n                // The script itself triggered a blocking JS dialog (alert/confirm/\n                // prompt/beforeunload). Chrome suspends Runtime.evaluate until the\n                // dialog is handled, and our Page.javascriptDialogOpening handler\n                // cancels the pending eval to avoid a 30s CDP timeout.\n                //\n                // From the user's perspective this is success, not failure — the\n                // script did exactly what they asked. The dialog is captured and\n                // accessible via getDialog() / getDialogText() / driver.dialogText\n                // and can be resolved with dialog(true|false). Return an empty\n                // response so extractJsValue yields null.\n                logger.debug(\"script opened a dialog, returning null: {}\", truncate(expression, 100));\n                return new CdpResponse(Map.of());","sourceCodeStart":1866,"sourceCodeEnd":1902,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-core/src/main/java/io/karatelabs/driver/cdp/CdpDriver.java#L1866-L1902","documentation":"When retries are exhausted and the main frame's execution context never registered (mainContextUnresolved), the driver degrades gracefully: it logs this warning and sends the Runtime.evaluate on CDP's default context instead of hard-failing. This matches cases like downloads/204/aborted navigations that clear the context without a replacement. Results from the default context can differ from the main-frame context, so the warning exists to make recurrences visible in CI logs.","triggerScenarios":"script()/eval where after maxRetries getFrameContext() still returns null — e.g. evaluating after a navigation that aborted, a download, or a 204 response wiped the execution context.","commonSituations":"Evaluating JS right after navigating to a download link or 204 endpoint, context lost after window.stop(), SPA teardown destroying the context, CI environments with slow context re-registration.","solutions":["Avoid evaluating JS immediately after non-document navigations (downloads/204) — the default-context fallback may return unexpected values.","Re-navigate to a real document before evaluating, restoring a proper main-frame context.","Increase retries/interval in driver config if the context is merely slow to register.","Treat this warning as a signal: investigate why the main context never came back (check for ERR_ABORTED in nearby logs)."],"exampleFix":"// before\ndriver.get('https://host/export'); // aborts/download, context never returns\ndriver.script(\"document.title\"); // falls back to default context, wrong scope\n// after\ndriver.get('https://host/index.html'); // re-establish a real document\nString title = driver.script(\"document.title\");","handlingStrategy":"fallback","validationCode":"// only evaluate when a real document is loaded\nif (driver.url().startsWith(\"http\") && !driver.url().equals(\"about:blank\")) { driver.script(\"document.title\"); }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Don't evaluate JS after download/204/aborted navigations","Re-navigate to a document to restore the main-frame context","Increase eval retries if the context is merely slow","Investigate this warning when it recurs — default-context results may be wrong"],"tags":["cdp","execution-context","fallback","graceful-degradation"],"backgroundTag":"js-execution-context-not-ready","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"}