{"record":{"id":"8ec18df88181f009","repo":"karatelabs/karate","slug":"element-vanished-between-existence-check-and-action-re","errorCode":null,"errorMessage":"element vanished between existence check and action, re-resolving ({}/{}): {}","messagePattern":"element vanished between existence check and action, re-resolving \\((.+?)/(.+?)\\): (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"karate-core/src/main/java/io/karatelabs/driver/cdp/CdpDriver.java","lineNumber":3263,"sourceCode":"     * </p>\n     * <p>\n     * Only the element-not-found marker is retried. Any other page-side JS error\n     * propagates untouched — a real bug in the page under test must not be retried into\n     * silence.\n     * </p>\n     */\n    private Object elementAction(String locator, String js) {\n        RuntimeException lastError = null;\n        for (int i = 0; i < ELEMENT_ACTION_ATTEMPTS; i++) {\n            retryIfNeeded(locator);\n            try {\n                return script(js);\n            } catch (RuntimeException e) {\n                if (!isElementVanished(e)) {\n                    throw e;\n                }\n                lastError = e;\n                logger.warn(\"element vanished between existence check and action, re-resolving ({}/{}): {}\",\n                        i + 1, ELEMENT_ACTION_ATTEMPTS, locator);\n                sleep(options.getRetryInterval());\n            }\n        }\n        throw new DriverException(\"element vanished during action after \" + ELEMENT_ACTION_ATTEMPTS\n                + \" re-resolve attempts: \" + locator + \" | \" + getDriverState(), lastError);\n    }\n\n    private static boolean isElementVanished(RuntimeException e) {\n        return e.getMessage() != null && e.getMessage().contains(Locators.ELEMENT_NOT_FOUND);\n    }\n\n    // ========== Wait Methods ==========\n\n    /**\n     * Wait for an element to exist.\n     */\n    public Element waitFor(String locator) {","sourceCodeStart":3245,"sourceCodeEnd":3281,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-core/src/main/java/io/karatelabs/driver/cdp/CdpDriver.java#L3245-L3281","documentation":"When performing an element action, the driver checks the element exists, resolves it, then runs the action JS — if the element is removed/re-rendered between check and action, the eval throws a 'vanished' error. The driver catches it, logs this warning with attempt count out of ELEMENT_ACTION_ATTEMPTS, re-resolves the locator, and retries after retryInterval. Only after exhausting all attempts does it throw DriverException with the driver state attached.","triggerScenarios":"SPA frameworks (React/Vue) re-rendering and replacing DOM nodes, animations detaching elements, navigation triggered mid-action, or timers removing nodes (toasts, skeletons) between the exists-check and click/script call.","commonSituations":"Clicking buttons in fast-updating UIs, interacting with elements inside polling lists, CI slowness widening the race window, or tests that don't wait for network-driven DOM replacement to settle.","solutions":["Wait for DOM stability before acting: waitFor the element, then wait for the triggering condition (network idle, spinner gone) before clicking.","Use stable locators — target nodes that persist (containers/parents) rather than nodes the framework swaps out.","Increase options retryInterval / retryCount so the built-in re-resolve attempts cover the re-render window.","If it still fails after all attempts, read the DriverException message — it includes getDriverState() (current URL, frame) to diagnose which transition removed the element."],"exampleFix":"// before\ndriver.click(\"div.results > div:nth-child(1) button\"); // row re-rendered mid-click\n// after\ndriver.waitFor(\"div.results\");\ndriver.click(\"div.results div.row[data-id='42'] button.approve\"); // stable data attribute","handlingStrategy":"retry","validationCode":"driver.waitFor(\"div.results\"); // element exists AND is stable before acting\ndriver.waitForUrl(\"**/list-loaded\");","typeGuard":null,"tryCatchPattern":"try {\n    driver.click(locator);\n} catch (Exception e) {\n    // DriverException 'element vanished during action after N attempts':\n    // message contains getDriverState() — check URL/frame to find the transition\n    throw e;\n}","preventionTips":["Use stable, data-attribute-based locators instead of nth-child positions","Wait for network/spinner completion before acting on dynamic lists","Tune retryInterval/retryCount for your app's re-render cadence","Read getDriverState() in the final DriverException to find the offending navigation"],"tags":[],"backgroundTag":null,"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"}