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

  1. Assign to a variable or a `obj.prop` / `obj[expr]` target instead of a call or literal.
  2. Fix the operand order if a comparison was intended (`==`/`===`).
  3. 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

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


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)