karatelabs/karate · error · DriverException

Element not found

Error message

Element not found: ${locator}

What it means

W3cDriver throws DriverException 'Element not found: <locator>' when the locator script executed successfully on both attempts but never returned a valid WebDriver element reference. Unlike 'locator failed twice', the lookup itself worked — the element simply does not exist in the current DOM.

Solutions

  1. Add an explicit wait: use waitFor(locator) or waitUntil for the element/condition before interacting
  2. Verify the selector in browser DevTools ($x / document.querySelector) on the exact page state
  3. Switch into the correct iframe or pierce the correct shadow DOM if the element is nested
  4. Fix the locator (stable attributes, data-testid) if the DOM changed

Example fix

// before
String id = driver.text("#submit-btn"); // throws if not yet rendered
// after
driver.waitFor("#submit-btn");
String id = driver.text("#submit-btn");
Defensive patterns

Strategy: validation

Validate before calling

// ensure element exists before acting
driver.waitFor(locator); // throws only after the wait timeout

Try / catch

try {
    driver.text(locator);
} catch (Exception e) {
    if (e.getMessage().startsWith("Element not found")) {
        // handle absence explicitly instead of failing
    }
}

Prevention

When it happens

Trigger: Calling driver.locate/find (directly or via click/input/text APIs) with a selector that matches nothing in the current page; calling immediately after navigation before the element is rendered; locating inside a closed or wrong shadow root/iframe.

Common situations: Incorrect id/class/XPath after a UI redesign; SPA content not yet rendered (no wait); element is inside an iframe that wasn't switched into; dynamic ids that change per load.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


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

Appendix: source

Thrown at karate-core/src/main/java/io/karatelabs/driver/w3c/W3cDriver.java:1049

        try {
            Object result = session.executeScript(js);
            if (W3cSession.isElementReference(result)) {
                return W3cSession.elementIdFrom(result);
            }
        } catch (Exception e) {
            logger.warn("locator failed, will retry once: {}", e.getMessage());
        }
        // Single retry after sleep
        sleep(options.getRetryInterval());
        try {
            Object result = session.executeScript(js);
            if (W3cSession.isElementReference(result)) {
                return W3cSession.elementIdFrom(result);
            }
        } catch (Exception e2) {
            throw new DriverException("locator failed twice: " + locator, e2);
        }
        throw new DriverException("Element not found: " + locator);
    }

    /**
     * Inject the Karate JS runtime (__kjs) into the browser if not already present.
     * Same pattern as CdpDriver — loads driver.js from classpath resources.
     * Provides wildcard locator resolution, shadow DOM traversal, and shared utilities.
     */
    private void ensureKjsRuntime() {
        try {
            // Guard on __kjs.resolve (the wildcard resolver), not merely __kjs — a co-installed
            // helper may seed a partial window.__kjs without it; driver.js extends, never clobbers.
            Object exists = session.executeScript(
                    "return typeof window.__kjs !== 'undefined' && typeof window.__kjs.resolve === 'function'");
            if (!Boolean.TRUE.equals(exists)) {
                session.executeScript(DRIVER_JS);
                logger.debug("Injected __kjs runtime into browser");
            }
        } catch (Exception e) {

View on GitHub (pinned to a22eb90246)