karatelabs/karate · error · JsErrorException (typeError)
cannot apply logical-assignment to
Error message
cannot apply logical-assignment to: ${node} What it means
A TypeError thrown when a logical assignment operator (`||=`, `&&=`, `??=`) is applied to a parse-tree node type that is neither a variable reference nor a member access. It is the default arm of the switch in PropertyAccess.logicalCompound, so it indicates an LHS shape the evaluator cannot treat as an assignment reference.
Solutions
- Rewrite the statement so the LHS is a variable or property access
- Compute the expression into a variable, then apply the logical assignment to that variable
- If the LHS appears valid, check for a parser regression and upgrade the engine
Example fix
// before foo().bar ??= 1; // after let f = foo(); f.bar ??= 1;
Defensive patterns
Strategy: validation
Validate before calling
// Reject logical-assignment statements whose LHS is not an identifier/member
if (/[^=!<>]=(&&|\|\||\?\?)?\s*(?![\w$.[])/.test(code)) { /* lint target */ }
// preferred: parse and check node type before eval
// valid = ['Identifier','MemberExpression'].includes(lhs.type) Type guard
function isLogicalAssignTarget(lhsNode) {
return lhsNode && ['Identifier','MemberExpression'].includes(lhsNode.type);
} Prevention
- Only use ||=, &&=, ??= on identifiers or property accesses
- Lint generated code for invalid assignment targets
- Avoid hand-editing minified/generated JS
When it happens
Trigger: Executing a script whose logical-assignment LHS parses as something other than REF_EXPR / REF_DOT_EXPR / REF_BRACKET_EXPR — e.g. `(a + b) ||= 1`, assignment to a call result, or a malformed/generated AST.
Common situations: Hand-edited JS with an expression on the left of `||=`; code generators emitting invalid assignment targets; engine/parser version mismatch.
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
- cannot apply compound assignment to
- cannot apply post inc/dec to
- cannot apply pre inc/dec to
- cannot get from
- cannot set on
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/3f8420f028cba9cf.
Report an issue: GitHub.
Appendix: source
Thrown at karate-js/src/main/java/io/karatelabs/js/PropertyAccess.java:453
PrivateAccess.set(site.target, site.privateName, newValue, context);
yield newValue;
}
if (site.receiver != null) {
// super reference — the fused by-index/by-name workers
// below have no receiver seam; run the generic sequence.
Object oldValue = siteRead(site, context);
if (context.isStopped()) yield null;
if (!shouldLogicalAssign(operator, oldValue)) yield oldValue;
Object newValue = Interpreter.eval(rhsNode, context);
if (context.isStopped()) yield null;
siteWrite(site, newValue, context, trackingNode);
yield newValue;
}
yield site.isIndex
? logicalCompoundByIndex(site.target, site.key, operator, rhsNode, context, trackingNode)
: logicalCompoundByName(site.target, (String) site.key, operator, rhsNode, context, trackingNode);
}
default -> throw JsErrorException.typeError("cannot apply logical-assignment to: " + node);
};
}
// Name-keyed REF_EXPR tails, outlined from their switch cases to keep the
// slot fast paths small enough to inline reliably.
private static Object compoundRefByName(Node node, CoreContext context, TokenType operator, Node rhsNode, Node trackingNode) {
String name = node.getText();
Object oldValue = context.get(name);
if (context.isStopped()) return Terms.UNDEFINED;
Object operand = Interpreter.eval(rhsNode, context);
if (context.isStopped()) return Terms.UNDEFINED;
Object newValue = applyOperator(oldValue, operator, operand, context);
context.update(name, newValue, trackingNode);
return newValue;
}
private static Object logicalCompoundRefByName(Node node, CoreContext context, TokenType operator, Node rhsNode, Node trackingNode) {View on GitHub (pinned to a22eb90246)