{"record":{"id":"1499bda6e8119bb1","repo":"karatelabs/karate","slug":"frame-context-not-received-via-event-falling-back-to","errorCode":null,"errorMessage":"frame context not received via event, falling back to isolated world: {}","messagePattern":"frame context not received via event, falling back to isolated world: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"karate-core/src/main/java/io/karatelabs/driver/cdp/CdpDriver.java","lineNumber":2531,"sourceCode":"        // First, wait for the main world context to arrive via Runtime.executionContextCreated —\n        // event-completed future (awaitFrameContext), same pattern as the main frame's\n        // mainContextReady, with the SAME 1s bound the old map-poll had so stranding can\n        // never be worse than before.\n        // IMPORTANT: Do NOT immediately fall back to Page.createIsolatedWorld - isolated worlds\n        // are separate JS contexts where variables set by page scripts (e.g., window.frameValue)\n        // are not visible. This caused flaky \"Switch back to main frame\" tests where\n        // script('window.frameValue') returned null because it ran in an isolated world\n        // instead of the iframe's main world.\n        if (!frameContexts.containsKey(frameId)) {\n            Integer contextId = awaitFrameContext(frameId, 1000);\n            if (contextId != null) {\n                logger.debug(\"frame context arrived via event: frameId={}\", frameId);\n            }\n        }\n        // Last resort: create an isolated world if the main world context never arrived.\n        // This is less ideal (page-set variables won't be visible) but allows basic DOM access.\n        if (!frameContexts.containsKey(frameId)) {\n            logger.warn(\"frame context not received via event, falling back to isolated world: {}\", frameId);\n            try {\n                CdpResponse response = cdp.method(\"Page.createIsolatedWorld\")\n                        .param(\"frameId\", frameId)\n                        .send();\n                Integer contextId = response.getResult(\"executionContextId\");\n                if (contextId != null) {\n                    frameContexts.put(frameId, contextId);\n                    // Complete the readiness future too, so a concurrent waiter on the\n                    // same frame observes the isolated world instead of timing out.\n                    completeFrameContext(frameId, contextId);\n                    logger.debug(\"created isolated world for frame {}: contextId={}\", frameId, contextId);\n                }\n            } catch (Exception e) {\n                logger.warn(\"failed to create isolated world for frame {}: {}\", frameId, e.getMessage());\n            }\n        }\n\n        // Verify the frame context is alive and ready for JS execution","sourceCodeStart":2513,"sourceCodeEnd":2549,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-core/src/main/java/io/karatelabs/driver/cdp/CdpDriver.java#L2513-L2549","documentation":"When switching into a same-origin frame, CdpDriver waits up to 1s for the frame's main-world execution context to arrive via the Runtime.executionContextCreated event. If it never arrives, it logs this warning and falls back to creating an isolated world via Page.createIsolatedWorld so basic DOM access still works. Page-set variables (window.* from page scripts) will NOT be visible in that isolated world.","triggerScenarios":"switchFrame() into a frame whose main-world executionContextCreated event was not observed within the 1s bound — frames created before the driver attached, very fast navigations, or frames whose context creation raced the CDP event stream.","commonSituations":"Switching to iframes immediately after page load, attaching the driver mid-page-life so early frames' context events were missed, or heavy pages where the frame's script context starts late.","solutions":["Retry the frame interaction after a short wait — once the frame's real context registers, subsequent evals hit the main world.","Reload the page or re-navigate before switchFrame so the context event fires while the driver is listening.","If you only need DOM reads, accept the isolated-world fallback; if you need page globals, wait for page readiness (e.g. waitForUrl) before switching frames.","Check that the frame URL is stable — rapidly re-navigating frames keep invalidating contexts."],"exampleFix":"// before\ndriver.switchFrame(\"#checkout-iframe\");\nString v = driver.script(\"document\", \"window.paymentConfig\"); // may be null in isolated world\n// after\ndriver.waitForUrl(\"**/checkout\");\ndriver.switchFrame(\"#checkout-iframe\");\nString v = driver.script(\"document\", \"window.paymentConfig\"); // main-world context now registered","handlingStrategy":"retry","validationCode":"// only switch after the frame has fully loaded\ndriver.waitFor(\"iframe#app\");\ndriver.waitForUrl(\"**/page-with-frame\");","typeGuard":null,"tryCatchPattern":"try {\n    driver.switchFrame(\"iframe#app\");\n    String v = driver.script(\"document\", \"window.appState\");\n    if (v == null) { /* likely isolated-world fallback: retry after wait */ }\n} catch (RuntimeException e) { /* retry switchFrame */ }","preventionTips":["Wait for page load / URL before switchFrame","Re-navigate or reload so context events fire while the driver is attached","Prefer main-world expectations only after the frame's scripts have run"],"tags":["cdp","iframe","isolated-world","race-condition"],"backgroundTag":"iframe-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"}