karatelabs/karate · warning

failed to create isolated world for frame

Error message

failed to create isolated world for frame {}: {}

What it means

After the event wait and the Page.createIsolatedWorld fallback both fail, CdpDriver logs that it could not create the isolated world for the frame and swallows the exception. Subsequent script evaluation against that frame will likely fail (no execution context). This indicates the CDP command itself errored — usually the frame no longer exists or the CDP session is unhealthy.

Solutions

  1. Re-locate and re-switch into the frame after it stabilizes — the old frameId is stale; retry the whole switchFrame.
  2. Add a wait for the frame to exist before switching (locator-based wait).
  3. Check browser health: if the tab crashed, re-launch the driver.
  4. Reduce parallelism or increase CDP timeouts if websocket congestion causes dropped sessions.

Example fix

// before
driver.switchFrame("iframe#ad"); // frame may vanish
// after
if (driver.exists("iframe#ad")) {
    driver.switchFrame("iframe#ad");
}
Defensive patterns

Strategy: retry

Validate before calling

if (driver.exists("iframe#ad")) { driver.switchFrame("iframe#ad"); }

Try / catch

try {
    driver.switchFrame(frameLocator);
} catch (RuntimeException e) {
    // frame may have detached; re-check existence and retry once
    if (driver.exists(frameLocator)) { driver.switchFrame(frameLocator); }
}

Prevention

When it happens

Trigger: ensureFrameContext() runs Page.createIsolatedWorld and the send() throws — frame detached/navigated between the call, invalid frameId, target crashed, or CDP connection dropped.

Common situations: Frames removed mid-interaction (ad iframes, SPA route changes), browser/tab closed while test was switching frames, or flaky CDP websocket during heavy parallel load.

Related errors


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

Appendix: source

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

        }
        // Last resort: create an isolated world if the main world context never arrived.
        // This is less ideal (page-set variables won't be visible) but allows basic DOM access.
        if (!frameContexts.containsKey(frameId)) {
            logger.warn("frame context not received via event, falling back to isolated world: {}", frameId);
            try {
                CdpResponse response = cdp.method("Page.createIsolatedWorld")
                        .param("frameId", frameId)
                        .send();
                Integer contextId = response.getResult("executionContextId");
                if (contextId != null) {
                    frameContexts.put(frameId, contextId);
                    // Complete the readiness future too, so a concurrent waiter on the
                    // same frame observes the isolated world instead of timing out.
                    completeFrameContext(frameId, contextId);
                    logger.debug("created isolated world for frame {}: contextId={}", frameId, contextId);
                }
            } catch (Exception e) {
                logger.warn("failed to create isolated world for frame {}: {}", frameId, e.getMessage());
            }
        }

        // Verify the frame context is alive and ready for JS execution
        // This is critical for flaky test prevention - the context may exist but
        // the frame's document might not be ready yet (still loading)
        waitForFrameContextReady(frameId);
    }

    /**
     * Wait for an OOPIF's document to leave the 'loading' state. cdp.sessionId is
     * already routed to the OOPIF session when this is called, so a contextId-less
     * Runtime.evaluate hits the OOPIF's default (main world) execution context.
     *
     * <p>When {@code expectedUrl} is non-empty, also require {@code document.URL} to
     * contain it. {@code window.location.href} updates as soon as a navigation is
     * committed in the browsing context — that's what {@code switchFrame} matches on
     * — but {@code document.URL} only updates when the new {@link org.w3c.dom.Document}

View on GitHub (pinned to a22eb90246)