karatelabs/karate · error
JS exception for: ->
Error message
JS exception for: {} -> {} What it means
When Runtime.evaluate returns exceptionDetails, CdpDriver throws RuntimeException("JS exception: <description>") using the exception object's description. This means the JavaScript expression executed via driver.script()/eval threw an uncaught error in the browser. The library surfaces the browser-side message so the caller can see the actual JS failure rather than a generic CDP error.
Solutions
- Read the description after 'JS exception: ' — it contains the browser's actual error (line number, message); fix the JS accordingly.
- Guard the expression: wrap risky JS in try/catch inside the expression, or check typeof before dereferencing (e.g. "window.foo ? foo.bar : null").
- Ensure the correct frame is active (switchFrame) before evaluating — the symbol may exist only in another frame.
- Wait for the page to be ready (waitForUrl / implicit waits) so page globals exist before eval.
Example fix
// before
String title = driver.script("document", "_.title || missingGlobal.name");
// after
String title = driver.script("document", "typeof missingGlobal !== 'undefined' ? missingGlobal.name : _.title"); Defensive patterns
Strategy: try-catch
Validate before calling
// before eval, ensure the symbol exists
Boolean ok = (Boolean) driver.script("window", "typeof paymentConfig !== 'undefined'");
if (!Boolean.TRUE.equals(ok)) { driver.waitFor("#config-loaded"); } Try / catch
try {
Object result = driver.script("document", expr);
} catch (RuntimeException e) {
if (e.getMessage() != null && e.getMessage().startsWith("JS exception: ")) {
// browser-side JS threw: fix expr or wait for page readiness
}
throw e;
} Prevention
- Test expressions in the browser DevTools console before embedding them
- Use typeof checks inside expressions instead of bare dereferences
- Wait for page/frame readiness before evaluating
- Throw Error objects (not strings) in page code so descriptions are detailed
When it happens
Trigger: Calling script(html, expression) or CdpDriver.script() with a JS expression that throws at evaluation time — e.g. referencing an undefined variable, calling a method on null/undefined, or JSON.parse of invalid data. The description branch is taken when exceptionDetails.exception.description is present (typical for Error/TypeError objects).
Common situations: Typos in injected JS, page scripts not yet defining a global the expression relies on, evaluating in the wrong frame/context where the expected object doesn't exist, or Chrome's stricter JS engine rejecting code that worked elsewhere.
Related errors
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/54e33dbd520aeaae.
Report an issue: GitHub.
Appendix: source
Thrown at karate-core/src/main/java/io/karatelabs/driver/cdp/CdpDriver.java:2020
return frameContexts.get(currentFrame.id);
}
private Object extractJsValue(CdpResponse response, String expression) {
if (response.isError()) {
String message = response.getErrorMessage();
if (message != null && message.contains("Object reference chain is too long")) {
logger.debug("script result not serializable, returning null: {}", truncate(expression, 100));
return null;
}
logger.warn("JS error for expression: {}", truncate(expression, 100));
throw new RuntimeException("JS error: " + response.getError());
}
Object exceptionDetails = response.getResult("exceptionDetails");
if (exceptionDetails != null) {
// Try to get detailed error message from exception object
String description = response.getResultAsString("exceptionDetails.exception.description");
if (description != null && !description.isEmpty()) {
logger.warn("JS exception for: {} -> {}", truncate(expression, 100), truncate(description, 200));
throw new RuntimeException("JS exception: " + description);
}
// Fall back to text (usually just "Uncaught")
String text = response.getResultAsString("exceptionDetails.text");
logger.warn("JS exception for: {} -> {}", truncate(expression, 100), text);
throw new RuntimeException("JS exception: " + text);
}
Object value = response.getResult("result.value");
logger.trace("script result: {}", value);
return value;
}
// ========== Screenshot ==========
/**
* Take screenshot and return PNG bytes.
*/
public byte[] screenshot() {View on GitHub (pinned to a22eb90246)