{"record":{"id":"85f9fe38b8122e90","repo":"karatelabs/karate","slug":"waituntil-timeout-locator-expression-expression","errorCode":null,"errorMessage":"waitUntil timeout: ${locator} expression: ${expression}","messagePattern":"waitUntil timeout: (.+?) expression: (.+?)","errorType":"exception","errorClass":"DriverException","httpStatus":null,"severity":"error","filePath":"karate-core/src/main/java/io/karatelabs/driver/w3c/W3cDriver.java","lineNumber":637,"sourceCode":"        return waitUntil(locator, expression, options.getTimeoutDuration());\n    }\n\n    @Override\n    public Element waitUntil(String locator, String expression, java.time.Duration timeout) {\n        long deadline = System.currentTimeMillis() + timeout.toMillis();\n        String js = Locators.scriptSelector(locator, expression);\n        while (System.currentTimeMillis() < deadline) {\n            try {\n                Object result = eval(js);\n                if (isTruthy(result)) {\n                    return BaseElement.existing(this, locator);\n                }\n            } catch (Exception e) {\n                // Element may not exist yet\n            }\n            sleep(options.getRetryInterval());\n        }\n        throw new DriverException(\"waitUntil timeout: \" + locator + \" expression: \" + expression);\n    }\n\n    @Override\n    public boolean waitUntil(String expression) {\n        return waitUntil(expression, options.getTimeoutDuration());\n    }\n\n    @Override\n    public boolean waitUntil(String expression, java.time.Duration timeout) {\n        long deadline = System.currentTimeMillis() + timeout.toMillis();\n        while (System.currentTimeMillis() < deadline) {\n            try {\n                Object result = eval(expression);\n                if (isTruthy(result)) {\n                    return true;\n                }\n            } catch (Exception e) {\n                // Ignore","sourceCodeStart":619,"sourceCodeEnd":655,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-core/src/main/java/io/karatelabs/driver/w3c/W3cDriver.java#L619-L655","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Run the expression manually in browser devtools against the element to verify it can return truthy","Increase the timeout via waitUntil(locator, expression, timeout)","Fix the expression syntax/reference (it is evaluated as JavaScript in the page)","Switch context (iframe/shadow) if the element is not in the main document"],"exampleFix":"// before\ndriver.waitUntil('.progress', \"_.classList.contains('done')\"); // never gets 'done'\n// after\ndriver.waitUntil('.progress', \"_.classList.contains('done')\", 30000); // plus verify app applies the class","handlingStrategy":"validation","validationCode":"// sanity-check the expression once before polling\nObject v = driver.script(locator, expression); // or eval manually in devtools","typeGuard":null,"tryCatchPattern":"try {\n    driver.waitUntil(locator, expression, timeout);\n} catch (DriverException e) {\n    // expression never truthy; re-evaluate once and log the actual value\n}","preventionTips":["Test the JS expression in devtools console first — poll exceptions are swallowed","Ensure the element is reachable from the main document (iframe/shadow)","Use boolean-returning expressions"],"tags":["webdriver","timeout","javascript","wait"],"backgroundTag":"request-timeout","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"}