{"record":{"id":"d961712d353922bc","repo":"karatelabs/karate","slug":"no-frame-at-index-index-after-retrycount-retries","errorCode":null,"errorMessage":"no frame at index: {index} after {retryCount} retries","messagePattern":"no frame at index: (.+?) after (.+?) retries","errorType":"exception","errorClass":"DriverException","httpStatus":null,"severity":"error","filePath":"karate-core/src/main/java/io/karatelabs/driver/cdp/CdpDriver.java","lineNumber":2276,"sourceCode":"     * Frames may load asynchronously after the main page.\n     */\n    @SuppressWarnings(\"unchecked\")\n    private List<Map<String, Object>> waitForChildFrames(int minIndex) {\n        // Use holder to capture result since lambda needs effectively final variable\n        final List<Map<String, Object>>[] holder = new List[1];\n\n        boolean found = retry(\"frame at index \" + minIndex, () -> {\n            CdpResponse response = cdp.method(\"Page.getFrameTree\").send();\n            List<Map<String, Object>> childFrames = response.getResult(\"frameTree.childFrames\");\n            if (childFrames != null && minIndex >= 0 && minIndex < childFrames.size()) {\n                holder[0] = childFrames;\n                return true;\n            }\n            return false;\n        });\n\n        if (!found) {\n            throw new DriverException(\"no frame at index: \" + minIndex + \" after \" + options.getRetryCount() + \" retries\");\n        }\n        return holder[0];\n    }\n\n    /**\n     * Switch to an iframe by locator (CSS, XPath, or wildcard).\n     * Pass null to switch back to the main frame.\n     *\n     * @param locator the locator for the iframe element, or null to return to main frame\n     */\n    @SuppressWarnings(\"unchecked\")\n    public void switchFrame(String locator) {\n        if (locator == null) {\n            // Switch back to main frame\n            currentFrame = null;\n            cdp.setSessionId(pageSessionId); // Restore main session\n            logger.debug(\"switched to main frame\");\n            return;","sourceCodeStart":2258,"sourceCodeEnd":2294,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-core/src/main/java/io/karatelabs/driver/cdp/CdpDriver.java#L2258-L2294","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Verify the index is 0-based and within the number of iframes on the page (driver.script(\"window.frames.length\"))","Increase retry count / retry interval in driver options if frames load late","Prefer switching by locator (CSS/XPath of the iframe element) instead of index","Wait for the iframe element to exist before switching (waitFor on the iframe selector)"],"exampleFix":"// before\ndriver.switchFrame(2); // only 1 iframe present\n// after\ndriver.waitFor(\"iframe#iframe-a\");\ndriver.switchFrame(\"iframe#iframe-a\"); // switch by locator","handlingStrategy":"validation","validationCode":"Number frameCount = (Number) driver.script(\"window.frames.length\");\nif (index < 0 || index >= frameCount.intValue()) throw new IllegalArgumentException(\"frame index \" + index + \" out of range, count=\" + frameCount);","typeGuard":null,"tryCatchPattern":"try { driver.switchFrame(index); } catch (DriverException e) { if (e.getMessage().startsWith(\"no frame at index\")) { driver.waitFor(\"iframe\"); driver.switchFrame(index); } else throw e; }","preventionTips":["Remember frame indices are 0-based","Wait for iframes to render before switching","Prefer locator-based frame switching over indices for stability","Increase retryCount in driver options for lazily-injected iframes"],"tags":["cdp","iframe","frame-switch","retry"],"backgroundTag":"index-out-of-range","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"}