karatelabs/karate · error · DriverException

timeout waiting for condition

Error message

timeout waiting for condition '${expression}' on element: ${locator}

What it means

CdpDriver.waitUntil(locator, expression, timeout) polls until the element exists AND the given JavaScript expression evaluated on that element is truthy; otherwise a DriverException naming the expression and locator is thrown. It is the generic per-element condition wait.

Solutions

  1. Test the expression directly with driver.script(locator, expression) and log the result to see what the page actually returns
  2. Verify the locator resolves and the expression returns a truthy JS value (true, non-empty string, non-zero number)
  3. Increase the timeout for genuinely slow async state
  4. Fix the preconditions (fill data, trigger event) so the condition can ever become true

Example fix

// before
driver.waitUntil("#status", "_.innerText == 'Done'", Duration.ofSeconds(3));
// after
String txt = (String) driver.script("#status", "_.innerText");
// log txt, correct expectation or timeout, e.g.:
driver.waitUntil("#status", "_.innerText.trim() == 'Done'", Duration.ofSeconds(15));
Defensive patterns

Strategy: validation

Validate before calling

// sanity-check the expression in-page before waiting
Object val = driver.script("#status", "_.innerText");
logger.debug("current status={}", val);

Try / catch

try {
    driver.waitUntil("#status", "_.innerText.trim() == 'Done'", Duration.ofSeconds(15));
} catch (DriverException e) {
    Object cur = driver.script("#status", "_.innerText");
    logger.error("condition not met; current value={}", cur);
    throw e;
}

Prevention

When it happens

Trigger: driver.waitUntil(locator, expression, duration) where the element is missing, or the JS expression (e.g. "_.value != ''", "arguments[0].classList.contains('ready')") keeps evaluating false/throws in the page until the timeout elapses.

Common situations: Expression syntax not valid in the page context (returns undefined rather than true); waiting on a state a slow backend never delivers; wrong locator so script() fails silently each poll; app never reaches the expected state because of a bug or failed pre-step.

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/54256b8e1311266b. Report an issue: GitHub.

Appendix: source

Thrown at karate-core/src/main/java/io/karatelabs/driver/cdp/CdpDriver.java:3411

    }

    /**
     * Wait until a JavaScript expression on an element evaluates to truthy.
     * The element is available as '_' in the expression.
     */
    public Element waitUntil(String locator, String expression) {
        return waitUntil(locator, expression, options.getTimeoutDuration());
    }

    /**
     * Wait until a JavaScript expression on an element evaluates to truthy.
     */
    public Element waitUntil(String locator, String expression, Duration timeout) {
        Element found = pollFor(timeout.toMillis(), options.getRetryInterval(),
                () -> exists(locator) && Terms.isTruthy(script(locator, expression))
                        ? BaseElement.existing(this, locator) : null);
        if (found == null) {
            throw new DriverException("timeout waiting for condition '" + expression + "' on element: " + locator);
        }
        return found;
    }

    /**
     * Wait until a JavaScript expression evaluates to truthy.
     */
    public boolean waitUntil(String expression) {
        return waitUntil(expression, options.getTimeoutDuration());
    }

    /**
     * Wait until a JavaScript expression evaluates to truthy with custom timeout.
     */
    public boolean waitUntil(String expression, Duration timeout) {
        boolean met = pollUntil(timeout.toMillis(), options.getRetryInterval(),
                () -> Terms.isTruthy(script(expression)));
        if (!met) {

View on GitHub (pinned to a22eb90246)