karatelabs/karate · error · java.lang.RuntimeException
expression
Error message
expression: <expr> - <cause message>
What it means
When evaluating a property/index access chain, PropertyAccess catches an underlying evaluation failure and, if it cannot resolve a bridge/type for the base object, rethrows as "expression: <expr> - <cause message>". It wraps the original cause, so the real failure (unknown variable, bad method, null base) is in the chained exception.
Solutions
- Read the chained cause message to find the real failure (undefined variable, missing method, etc.).
- Assert/validate the variable exists before the expression: use karate.match or a JS typeof/null check.
- Fix the typo or ensure the upstream step that produces the base object actually ran and set the value.
Example fix
// before (Karate script) * def x = response.data.items[0].name // expression: response.data.items[0].name - ... if data missing // after * assert response.data != null * def items = response.data.items || [] * def x = items.length ? items[0].name : null
Defensive patterns
Strategy: validation
Validate before calling
// Karate script: validate base values before member access * assert response != null && response.data != null * def items = response.data ? (response.data.items || []) : []
Type guard
// JS in Karate
function safeGet(obj, path) {
return path.split('.').reduce((o, k) => (o == null ? undefined : o[k]), obj);
} Try / catch
try {
value = karate.eval(expression);
} catch (RuntimeException e) {
if (e.getMessage().startsWith("expression:")) {
logger.warn("failed expression: {} cause: {}", expression, e.getCause());
value = null; // or default
} else throw e;
} Prevention
- Always verify variables/fields exist before chaining member access.
- Use optional chaining (?.) in JS expressions to short-circuit null/undefined.
- Check the wrapped cause (getCause()) — it names the real failure.
- Assert upstream API responses with karate.match before using nested fields.
When it happens
Trigger: A dot/bracket access chain where an intermediate evaluation throws and the base object cannot be determined — e.g. referencing an undefined variable then calling a member (x.foo() with x undefined), or an expression on a null/unknown context value.
Common situations: Typos in Karate script variables, accessing members of a response field that does not exist, calling Java interop methods on undefined values, schema/config keys not set before the expression runs.
Related errors
- cannot read properties of
- scenario match evaluation failed at line
- a class declaration may not be the body of
- a function declaration may not be the body of
- a lexical declaration may not be the body of
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/71ad1b93d745f791.
Report an issue: GitHub.
Appendix: source
Thrown at karate-js/src/main/java/io/karatelabs/js/PropertyAccess.java:735
object = Interpreter.eval(node.getFirst(), context);
} catch (Exception e) {
if (context.root.bridge != null) {
String base = node.getFirst().getText();
String path = base + "." + name;
ExternalAccess ja = context.root.bridge.forType(path);
if (ja != null) {
if (wantReceiver) context.callReceiver = null;
if (functionCall) {
return (JsConstructor) (c, args) -> ja.construct(args);
}
return ja;
}
object = context.root.bridge.forType(base);
} else {
object = null;
}
if (object == null) {
throw new RuntimeException("expression: " + node.getFirst().getText() + " - " + e.getMessage(), e);
}
}
// Propagate short-circuit from a deeper ?. step.
if (object == SHORT_CIRCUITED) return SHORT_CIRCUITED;
// Local ?. fires here.
if (optional && (object == null || object == Terms.UNDEFINED)) return SHORT_CIRCUITED;
} else {
optional = true;
if (node.get(1).type == NodeType.REF_BRACKET_EXPR) {
object = Interpreter.eval(node.getFirst(), context);
if (object == SHORT_CIRCUITED) return SHORT_CIRCUITED;
// ?.[expr] fires here — index is not evaluated when short-circuiting.
if (object == null || object == Terms.UNDEFINED) return SHORT_CIRCUITED;
Object index = Interpreter.eval(node.get(1).get(2), context);
Object v = getByIndex(object, index, false, context, functionCall);
if (wantReceiver) context.callReceiver = object;
return v;
} else {View on GitHub (pinned to a22eb90246)