karatelabs/karate · error · DriverException

javascript failed

Error message

javascript failed: ${message}

What it means

W3cDriver.eval executes JavaScript in the page via the WebDriver executeScript endpoint. It retries once on failure (logging 'javascript failed, will retry once'); if the retry also throws, it wraps the error in DriverException 'javascript failed: <message>'. All element operations (click, input, clear, focus, scroll) go through this path, so any of them can surface this error.

Solutions

  1. Read the nested message to see the actual WebDriver/JS error
  2. Wait for page readiness (e.g. waitFor/navigation settling) before the element operation, or add retry logic in the test
  3. Fix syntax errors in any custom JS passed to script()
  4. If the session is stale, re-initialize the driver/browser
  5. Handle unexpected dialogs (accept/dismiss) before scripting

Example fix

// before
click('#submit') immediately after navigation triggers
// after
waitFor('#submit');
click('#submit');
Defensive patterns

Strategy: retry

Validate before calling

// wait for page readiness before element ops
driver.waitFor("#submit");

Try / catch

try {
    driver.click(selector);
} catch (DriverException e) {
    if (e.getMessage().startsWith("javascript failed:")) {
        driver.waitFor(selector); // settle page, retry once
        driver.click(selector);
    } else throw e;
}

Prevention

When it happens

Trigger: executeScript throws twice in a row — e.g. the page navigated or context was destroyed mid-script, the injected expression is invalid JS, or the WebDriver session is stale/dead.

Common situations: Clicking or typing during a page navigation; SPA replacing DOM nodes under the script; session invalidated after browser crash or manual close; a selector/JS snippet with a syntax error; alert dialog blocking script execution.

Related errors


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

Appendix: source

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

        // - Starts with a bare expression (no var/let/const/if/for) → prefix "return"
        // - Statement blocks (var/let/const/if/for/try) → execute as-is (no return value)
        // Inject __kjs runtime if the script references it (wildcard locators, shadow DOM)
        if (js.contains("__kjs")) {
            ensureKjsRuntime();
        }
        String expression = prefixReturnIfNeeded(js);
        Object result;
        try {
            result = session.executeScript(expression);
        } catch (Exception e) {
            // v1 pattern: single retry on JS error — handles transient page-load timing issues
            logger.warn("javascript failed, will retry once: {}", e.getMessage());
            sleep(options.getRetryInterval());
            try {
                result = session.executeScript(expression);
            } catch (Exception e2) {
                logger.error("javascript failed twice: {}", e2.getMessage());
                throw new DriverException("javascript failed: " + e2.getMessage(), e2);
            }
        }
        return wrapElementReferences(result);
    }

    @SuppressWarnings("unchecked")
    private Object wrapElementReferences(Object result) {
        if (W3cSession.isElementReference(result)) {
            String elementId = W3cSession.elementIdFrom(result);
            return new W3cElement(this, "(eval result)", true, elementId, session);
        }
        if (result instanceof List) {
            List<Object> list = (List<Object>) result;
            boolean hasElements = list.stream().anyMatch(W3cSession::isElementReference);
            if (hasElements) {
                List<Object> wrapped = new ArrayList<>();
                for (Object item : list) {
                    if (W3cSession.isElementReference(item)) {

View on GitHub (pinned to a22eb90246)