{"record":{"id":"e0a5455fe4e26855","repo":"karatelabs/karate","slug":"invalid-sitename-call-expression","errorCode":null,"errorMessage":"invalid ${siteName}: call expression","messagePattern":"invalid (.+?): call expression","errorType":"exception","errorClass":"ParserException","httpStatus":null,"severity":"error","filePath":"karate-js/src/main/java/io/karatelabs/parser/JsParser.java","lineNumber":1742,"sourceCode":"                    throw new ParserException(\"invalid \" + siteName + \": this\");\n                }\n            }\n            case REF_DOT_EXPR, REF_BRACKET_EXPR -> {\n                // Plain member access; a `?.` would have been caught earlier by\n                // the optional-chain branch above with a more specific message.\n                // `import.meta` is a meta-property whose AssignmentTargetType is\n                // invalid; `import` is not a reserved word in our lexer so it\n                // parses as a normal REF_DOT_EXPR — flag the literal shape here.\n                if (n.type == NodeType.REF_DOT_EXPR && isImportMeta(n)) {\n                    throw new ParserException(\"invalid \" + siteName + \": import.meta\");\n                }\n            }\n            case FN_CALL_EXPR -> {\n                // Web-compat carve-out (Annex B B.3.5): allow `f() = 1` in non-strict mode.\n                // Logical-assignment operators (||=, &&=, ??=) are ES2021 and the carve-out\n                // does NOT apply to them; the caller passes noCallCarveOut=true in that case.\n                if (noCallCarveOut) {\n                    throw new ParserException(\"invalid \" + siteName + \": call expression\");\n                }\n            }\n            default ->\n                    throw new ParserException(\"invalid \" + siteName + \": \"\n                            + n.type.name() + \" is not a valid assignment target\");\n        }\n    }\n\n    /**\n     * Strip thin {@code EXPR} / {@code EXPR_LIST} single-child wrappers introduced\n     * by the parser so that callers can inspect the underlying expression shape.\n     * Returns the node unchanged once the wrappers run out or the node has more\n     * than one child.\n     */\n    private static Node stripExprWrappers(Node n) {\n        while (n != null && n.size() == 1\n                && (n.type == NodeType.EXPR || n.type == NodeType.EXPR_LIST)) {\n            n = n.get(0);","sourceCodeStart":1724,"sourceCodeEnd":1760,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-js/src/main/java/io/karatelabs/parser/JsParser.java#L1724-L1760","documentation":"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.","triggerScenarios":"Code like `f() ||= true`, `obj.get() &&= x`, or `g() ??= y`, or `f() = 1` inside strict-mode code where the call-carve-out is disabled.","commonSituations":"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.","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"],"exampleFix":"// before\nobj.getValue() ||= 42;\n// after\nif (obj.getValue() == null) { obj.setValue(42); }","handlingStrategy":"validation","validationCode":"if (/\\w\\(\\)\\s*(\\|\\|=|&&=|\\?\\?=|=)/.test(code)) {\n  throw new Error('assignment to call expression is not allowed here');\n}","typeGuard":"function isCallTarget(node) {\n  return node.type === 'AssignmentExpression' && node.left.type === 'CallExpression';\n}","tryCatchPattern":"try {\n  karate.eval(code);\n} catch (e) {\n  if (String(e.message).includes('call expression')) { /* rewrite assignment */ }\n  throw e;\n}","preventionTips":["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"],"tags":["javascript","parser","assignment-target","strict-mode"],"backgroundTag":"unsupported-operation","analyzedSha":"a22eb90246d958d15a47bf436693d0121ad2812d","analyzedAt":"2026-09-12T09:01:00.220Z","contentChangedAt":"2026-09-12T09:01:00.220Z","schemaVersion":2},"datasetVersion":"2026-09-16T19:17:19.609Z"}