karatelabs/karate · error
element vanished between existence check and action…
Error message
element vanished between existence check and action, re-resolving ({}/{}): {} What it means
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.
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.
Example fix
// before
driver.click("div.results > div:nth-child(1) button"); // row re-rendered mid-click
// after
driver.waitFor("div.results");
driver.click("div.results div.row[data-id='42'] button.approve"); // stable data attribute Defensive patterns
Strategy: retry
Validate before calling
driver.waitFor("div.results"); // element exists AND is stable before acting
driver.waitForUrl("**/list-loaded"); Try / catch
try {
driver.click(locator);
} catch (Exception e) {
// DriverException 'element vanished during action after N attempts':
// message contains getDriverState() — check URL/frame to find the transition
throw e;
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/8ec18df88181f009.
Report an issue: GitHub.
Appendix: source
Thrown at karate-core/src/main/java/io/karatelabs/driver/cdp/CdpDriver.java:3263
* </p>
* <p>
* Only the element-not-found marker is retried. Any other page-side JS error
* propagates untouched — a real bug in the page under test must not be retried into
* silence.
* </p>
*/
private Object elementAction(String locator, String js) {
RuntimeException lastError = null;
for (int i = 0; i < ELEMENT_ACTION_ATTEMPTS; i++) {
retryIfNeeded(locator);
try {
return script(js);
} catch (RuntimeException e) {
if (!isElementVanished(e)) {
throw e;
}
lastError = e;
logger.warn("element vanished between existence check and action, re-resolving ({}/{}): {}",
i + 1, ELEMENT_ACTION_ATTEMPTS, locator);
sleep(options.getRetryInterval());
}
}
throw new DriverException("element vanished during action after " + ELEMENT_ACTION_ATTEMPTS
+ " re-resolve attempts: " + locator + " | " + getDriverState(), lastError);
}
private static boolean isElementVanished(RuntimeException e) {
return e.getMessage() != null && e.getMessage().contains(Locators.ELEMENT_NOT_FOUND);
}
// ========== Wait Methods ==========
/**
* Wait for an element to exist.
*/
public Element waitFor(String locator) {View on GitHub (pinned to a22eb90246)