karatelabs/karate · error · DriverException

waitUntil timeout: expression

Error message

waitUntil timeout: ${locator} expression: ${expression}

What it means

W3cDriver.waitUntil(locator, expression) repeatedly evaluates a JS expression scoped to the element, swallowing per-poll exceptions since the element may not exist yet. If the expression never returns truthy within the timeout, a DriverException naming the locator and expression is thrown.

Solutions

  1. Run the expression manually in browser devtools against the element to verify it can return truthy
  2. Increase the timeout via waitUntil(locator, expression, timeout)
  3. Fix the expression syntax/reference (it is evaluated as JavaScript in the page)
  4. Switch context (iframe/shadow) if the element is not in the main document

Example fix

// before
driver.waitUntil('.progress', "_.classList.contains('done')"); // never gets 'done'
// after
driver.waitUntil('.progress', "_.classList.contains('done')", 30000); // plus verify app applies the class
Defensive patterns

Strategy: validation

Validate before calling

// sanity-check the expression once before polling
Object v = driver.script(locator, expression); // or eval manually in devtools

Try / catch

try {
    driver.waitUntil(locator, expression, timeout);
} catch (DriverException e) {
    // expression never truthy; re-evaluate once and log the actual value
}

Prevention

When it happens

Trigger: Calling driver.waitUntil(locator, jsExpression) where the element never appears, or the expression keeps evaluating falsy (e.g. checking a class/style/state that never changes) within the timeout.

Common situations: JS expression has a typo or returns a non-boolean that is falsy; waiting for a CSS class the app never applies; element inside iframe/shadow DOM so the scoped lookup fails every poll; slow async update exceeding timeout.

Understand the failure class

Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.

Related errors


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

Appendix: source

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

        return waitUntil(locator, expression, options.getTimeoutDuration());
    }

    @Override
    public Element waitUntil(String locator, String expression, java.time.Duration timeout) {
        long deadline = System.currentTimeMillis() + timeout.toMillis();
        String js = Locators.scriptSelector(locator, expression);
        while (System.currentTimeMillis() < deadline) {
            try {
                Object result = eval(js);
                if (isTruthy(result)) {
                    return BaseElement.existing(this, locator);
                }
            } catch (Exception e) {
                // Element may not exist yet
            }
            sleep(options.getRetryInterval());
        }
        throw new DriverException("waitUntil timeout: " + locator + " expression: " + expression);
    }

    @Override
    public boolean waitUntil(String expression) {
        return waitUntil(expression, options.getTimeoutDuration());
    }

    @Override
    public boolean waitUntil(String expression, java.time.Duration timeout) {
        long deadline = System.currentTimeMillis() + timeout.toMillis();
        while (System.currentTimeMillis() < deadline) {
            try {
                Object result = eval(expression);
                if (isTruthy(result)) {
                    return true;
                }
            } catch (Exception e) {
                // Ignore

View on GitHub (pinned to a22eb90246)