karatelabs/karate · error · ParserException
invalid : call expression
Error message
invalid ${siteName}: call expression What it means
Assigning to a function call (`f() = 1`) is invalid in strict mode and under ES2021 logical-assignment operators. Karate implements the Annex B.3.5 web-compat carve-out for plain calls in non-strict mode, but when the caller passes noCallCarveOut=true (e.g. for `||=`, `&&=`, `??=`), call expressions on the left side are rejected.
Solutions
- Assign to a variable or property instead of a call result, then call again if needed
- Replace `f() ||= v` with an explicit check: `let r = f(); if (!r) r = v;`
- Remove `=`/logical-assignment after the call; call expressions produce values, not references
Example fix
// before
obj.getValue() ||= 42;
// after
if (obj.getValue() == null) { obj.setValue(42); } Defensive patterns
Strategy: validation
Validate before calling
if (/\w\(\)\s*(\|\|=|&&=|\?\?=|=)/.test(code)) {
throw new Error('assignment to call expression is not allowed here');
} Type guard
function isCallTarget(node) {
return node.type === 'AssignmentExpression' && node.left.type === 'CallExpression';
} Try / catch
try {
karate.eval(code);
} catch (e) {
if (String(e.message).includes('call expression')) { /* rewrite assignment */ }
throw e;
} Prevention
- Avoid logical-assignment operators (||=, &&=, ??=) after call expressions
- Assign call results to variables before conditional updates
- Note Annex B carve-out only applies to plain `=` in non-strict mode
When it happens
Trigger: Code like `f() ||= true`, `obj.get() &&= x`, or `g() ??= y`, or `f() = 1` inside strict-mode code where the call-carve-out is disabled.
Common situations: Using ES2021 logical assignment on the result of a getter or function call; refactoring `a.b() = ...` patterns from non-strict legacy code into strict contexts.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- ' ' is not a valid function name in strict mode
- duplicate parameter name
- identifier ' ' has already been declared
- invalid assignment to
- octal literals are not allowed in strict mode
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/e0a5455fe4e26855.
Report an issue: GitHub.
Appendix: source
Thrown at karate-js/src/main/java/io/karatelabs/parser/JsParser.java:1742
throw new ParserException("invalid " + siteName + ": this");
}
}
case REF_DOT_EXPR, REF_BRACKET_EXPR -> {
// Plain member access; a `?.` would have been caught earlier by
// the optional-chain branch above with a more specific message.
// `import.meta` is a meta-property whose AssignmentTargetType is
// invalid; `import` is not a reserved word in our lexer so it
// parses as a normal REF_DOT_EXPR — flag the literal shape here.
if (n.type == NodeType.REF_DOT_EXPR && isImportMeta(n)) {
throw new ParserException("invalid " + siteName + ": import.meta");
}
}
case FN_CALL_EXPR -> {
// Web-compat carve-out (Annex B B.3.5): allow `f() = 1` in non-strict mode.
// Logical-assignment operators (||=, &&=, ??=) are ES2021 and the carve-out
// does NOT apply to them; the caller passes noCallCarveOut=true in that case.
if (noCallCarveOut) {
throw new ParserException("invalid " + siteName + ": call expression");
}
}
default ->
throw new ParserException("invalid " + siteName + ": "
+ n.type.name() + " is not a valid assignment target");
}
}
/**
* Strip thin {@code EXPR} / {@code EXPR_LIST} single-child wrappers introduced
* by the parser so that callers can inspect the underlying expression shape.
* Returns the node unchanged once the wrappers run out or the node has more
* than one child.
*/
private static Node stripExprWrappers(Node n) {
while (n != null && n.size() == 1
&& (n.type == NodeType.EXPR || n.type == NodeType.EXPR_LIST)) {
n = n.get(0);View on GitHub (pinned to a22eb90246)