karatelabs/karate · error · JsErrorException (typeError)
cannot set on
Error message
cannot set on: ${node} What it means
`PropertyAccess.set` only knows how to write through dot/bracket reference nodes (resolving an AccessSite first). Any other node kind on the left of an assignment reaches the default branch and throws this TypeError naming the node, because the engine cannot form a writable reference from it.
Solutions
- Assign to a variable or a `obj.prop` / `obj[expr]` target instead of a call or literal.
- Fix the operand order if a comparison was intended (`==`/`===`).
- Use destructuring syntax `let {a, b} = ...` rather than assigning to a parenthesized list.
Example fix
// before getResult() = 5; // TypeError: cannot set on: FN_CALL... // after var result = getResult();
Defensive patterns
Strategy: validation
Validate before calling
// ensure assignment LHS is an identifier or property path
const lhs = code.split('=')[0].trim();
if (!/^[A-Za-z_$][\w$]*(\.[\w$]+|\[[^\]]+\])*$/.test(lhs)) throw new Error('invalid assignment target: ' + lhs); Type guard
function isWritableTarget(node) { return ['REF_DOT_EXPR','REF_BRACKET_EXPR','IDENT'].includes(node && node.type); } Try / catch
try { engine.set(name, value); } catch (e) { if (String(e.message).startsWith('cannot set on:')) { /* normalize the LHS */ } else { throw e; } } Prevention
- Assign only to variables or obj.prop / obj[expr].
- Avoid calls, literals, and parenthesized lists on the LHS of `=`.
- Use destructuring declarations instead of assigning to expressions.
When it happens
Trigger: Assigning to an expression that is not a dot or bracket property reference, e.g. `f() = 1`, `(a, b) = 2`, or a literal on the LHS of `=` evaluated through the set path.
Common situations: Typos like `if (x = 5)` reversed (`5 = x`); template-generated code producing invalid assignment targets; destructuring attempted with plain `=` against a call result.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- cannot get from
- cannot write to optional call expression
- AggregateError requires an iterable of errors
- Array.from requires an iterable or array-like object, not
- Array.prototype.* called on null or undefined
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/1e4c74b61d1e8cba.
Report an issue: GitHub.
Appendix: source
Thrown at karate-js/src/main/java/io/karatelabs/js/PropertyAccess.java:297
*/
static void set(Node node, CoreContext context, Object value, Node trackingNode) {
switch (node.type) {
case REF_EXPR -> {
int slot = node.slot;
Object[] frame;
if (slot >= 0 && (frame = context.frame) != null && frame[slot] != SlotTable.UNDECLARED) {
context.updateSlot(slot, value, trackingNode);
} else {
context.update(node.getText(), value, trackingNode);
}
}
case REF_DOT_EXPR, REF_BRACKET_EXPR -> {
AccessSite site = resolveWriteSite(node, context);
if (site == null || site == SHORT_CIRCUIT_SITE) return;
if (site.privateName != null) PrivateAccess.set(site.target, site.privateName, value, context);
else siteWrite(site, value, context, trackingNode);
}
default -> throw JsErrorException.typeError("cannot set on: " + node);
}
}
//=== Assignment and compound operations ===
/**
* Simple assignment (`=`) in spec §13.15.2 evaluation order: the LHS
* Reference — base object and computed key — is evaluated BEFORE the RHS
* expression, and an abrupt completion at either step skips the write.
* Returns the assigned value (the value of the whole assignment
* expression).
*/
static Object assign(Node node, CoreContext context, Node rhsNode, Node trackingNode) {
return switch (node.type) {
case REF_EXPR -> {
// An identifier Reference resolves without observable side
// effects; an unresolvable name only throws at PutValue time,
// which is after the RHS has been evaluated.View on GitHub (pinned to a22eb90246)