karatelabs/karate · error · DriverException

no frame at index: after retries

Error message

no frame at index: {index} after {retryCount} retries

What it means

When switching to a frame by zero-based index, Karate polls for a matching child frame until the retry count is exhausted. If no frame at that index exists after all retries, it throws this DriverException with the requested index and retry count.

Solutions

  1. Verify the index is 0-based and within the number of iframes on the page (driver.script("window.frames.length"))
  2. Increase retry count / retry interval in driver options if frames load late
  3. Prefer switching by locator (CSS/XPath of the iframe element) instead of index
  4. Wait for the iframe element to exist before switching (waitFor on the iframe selector)

Example fix

// before
driver.switchFrame(2); // only 1 iframe present
// after
driver.waitFor("iframe#iframe-a");
driver.switchFrame("iframe#iframe-a"); // switch by locator
Defensive patterns

Strategy: validation

Validate before calling

Number frameCount = (Number) driver.script("window.frames.length");
if (index < 0 || index >= frameCount.intValue()) throw new IllegalArgumentException("frame index " + index + " out of range, count=" + frameCount);

Try / catch

try { driver.switchFrame(index); } catch (DriverException e) { if (e.getMessage().startsWith("no frame at index")) { driver.waitFor("iframe"); driver.switchFrame(index); } else throw e; }

Prevention

When it happens

Trigger: driver.switchFrame(index) where the page has fewer frames than the given index, or frames appear later than the retry window allows (iframe injected by JS after load).

Common situations: Off-by-one assumptions (frames are 0-based); iframes rendered lazily by SPA frameworks after Karate already polled; pages whose ad/iframes are removed by blockers, shifting indices.

Related errors


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

Appendix: source

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

     * Frames may load asynchronously after the main page.
     */
    @SuppressWarnings("unchecked")
    private List<Map<String, Object>> waitForChildFrames(int minIndex) {
        // Use holder to capture result since lambda needs effectively final variable
        final List<Map<String, Object>>[] holder = new List[1];

        boolean found = retry("frame at index " + minIndex, () -> {
            CdpResponse response = cdp.method("Page.getFrameTree").send();
            List<Map<String, Object>> childFrames = response.getResult("frameTree.childFrames");
            if (childFrames != null && minIndex >= 0 && minIndex < childFrames.size()) {
                holder[0] = childFrames;
                return true;
            }
            return false;
        });

        if (!found) {
            throw new DriverException("no frame at index: " + minIndex + " after " + options.getRetryCount() + " retries");
        }
        return holder[0];
    }

    /**
     * Switch to an iframe by locator (CSS, XPath, or wildcard).
     * Pass null to switch back to the main frame.
     *
     * @param locator the locator for the iframe element, or null to return to main frame
     */
    @SuppressWarnings("unchecked")
    public void switchFrame(String locator) {
        if (locator == null) {
            // Switch back to main frame
            currentFrame = null;
            cdp.setSessionId(pageSessionId); // Restore main session
            logger.debug("switched to main frame");
            return;

View on GitHub (pinned to a22eb90246)