{"record":{"id":"d253ae50a2c6cab2","repo":"karatelabs/karate","slug":"optional-chain-cannot-be-the-operand-of-prefix","errorCode":null,"errorMessage":"optional chain cannot be the operand of prefix ++/--","messagePattern":"optional chain cannot be the operand of prefix \\+\\+/--","errorType":"exception","errorClass":"ParserException","httpStatus":null,"severity":"error","filePath":"karate-js/src/main/java/io/karatelabs/parser/JsParser.java","lineNumber":536,"sourceCode":"            case MATH_POST_EXPR -> {\n                // children: [operand, ++/--]\n                if (node.size() > 0) {\n                    Node operand = node.getFirst();\n                    if (sawOptionalChain && subtreeContainsOptionalChain(operand)) {\n                        throw new ParserException(\"optional chain cannot be the operand of postfix ++/--\");\n                    }\n                    checkSimpleAssignmentTarget(operand, \"operand of postfix update\", false);\n                }\n            }\n            case MATH_PRE_EXPR -> {\n                // children: [op, operand] — only ++/-- need a valid update target;\n                // unary +/- have no assignment side and parse the same shape.\n                if (node.size() > 1) {\n                    Node op = node.getFirst();\n                    if (op.isToken() && (op.token.type == PLUS_PLUS || op.token.type == MINUS_MINUS)) {\n                        Node operand = node.get(1);\n                        if (sawOptionalChain && subtreeContainsOptionalChain(operand)) {\n                            throw new ParserException(\"optional chain cannot be the operand of prefix ++/--\");\n                        }\n                        checkSimpleAssignmentTarget(operand, \"operand of prefix update\", false);\n                    }\n                }\n            }\n            case FN_TAGGED_TEMPLATE_EXPR -> {\n                if (sawOptionalChain && node.size() > 0\n                        && subtreeContainsOptionalChain(node.getFirst())) {\n                    throw new ParserException(\"tagged template literal cannot follow an optional chain\");\n                }\n            }\n            // A FunctionDeclaration is a StatementListItem, never a Statement, so it\n            // may not be the sole body of an iteration statement (§13.7). Unlike the\n            // `if` clause (Annex B.3.4) there is no web-compat carve-out, so this is an\n            // early error in BOTH sloppy and strict code — hence it lives here, not in\n            // the strict-gated walk. `for (…) { function f(){} }` stays legal: the body\n            // Statement wraps a BLOCK, so its direct child is BLOCK, not FN_EXPR.\n            // A LexicalDeclaration (let/const) and a ClassDeclaration are likewise","sourceCodeStart":518,"sourceCodeEnd":554,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-js/src/main/java/io/karatelabs/parser/JsParser.java#L518-L554","documentation":"Prefix `++`/`--` require a valid simple assignment target; an optional chain (`++a?.b`) is not one. The Karate JS parser throws this early error when a prefix-update operand subtree contains an optional chain. Guard or split the expression.","triggerScenarios":"Parsing `++a?.b` or `--obj?.count`, detected in earlyErrorNodeChecks for MATH_PRE_EXPR nodes where the operator is `++`/`--` and the operand contains `?.`.","commonSituations":"Same as postfix updates but with the operator in front — often from reordering code or from authors assuming `?.` yields a writable reference; common in refactored null-guard code.","solutions":["Guard with an if: `if (a) ++a.b;`","Compute the value separately: `if (a) a.b = (a?.b ?? 0) + 1;`","Drop the `?.` when the object is guaranteed non-nullish: `++a.b`."],"exampleFix":"// before\n++stats?.hits;\n// after\nif (stats) ++stats.hits;","handlingStrategy":"validation","validationCode":"// reject optional chains under prefix ++/--\nfunction validPrefixUpdate(src) { return !/(\\+\\+|--)\\s*[\\w$.]+\\?\\./.test(src); }","typeGuard":null,"tryCatchPattern":"try { karate.eval(expr); } catch (e) { if (String(e).includes('optional chain cannot be the operand of prefix')) { /* guard with if */ } }","preventionTips":["Never write `++`/`--` before a chain that contains `?.`.","Split read-increment-write into explicit guarded statements.","Review optional-chaining refactors for adjacent mutation operators."],"tags":["javascript","parser","syntax-error","optional-chaining"],"backgroundTag":"javascript-syntax-error","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"}