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
- Read the nested message to see the actual WebDriver/JS error
- Wait for page readiness (e.g. waitFor/navigation settling) before the element operation, or add retry logic in the test
- Fix syntax errors in any custom JS passed to script()
- If the session is stale, re-initialize the driver/browser
- 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
- Use waitFor/waitUntil before interacting with elements after navigation
- Avoid custom JS eval strings without testing them in devtools
- Handle or suppress dialogs before scripting
- Recreate the driver after browser crashes instead of reusing a dead session
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
- waitUntil timeout: expression
- waitUntil timeout
- ${pe.getMessage()}
- retry condition evaluation failed
- retry succeeded after
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)