{"record":{"id":"915721b3f8e678d4","repo":"karatelabs/karate","slug":"invalid-destructuring-rest-element-must-be-the-last-binding","errorCode":null,"errorMessage":"invalid destructuring: rest element must be the last binding element","messagePattern":"invalid destructuring: rest element must be the last binding element","errorType":"exception","errorClass":"ParserException","httpStatus":null,"severity":"error","filePath":"karate-js/src/main/java/io/karatelabs/parser/JsParser.java","lineNumber":1536,"sourceCode":"     *       AssignmentExpression).</li>\n     * </ul>\n     * Called only when the surrounding {@code LIT_ARRAY} is in pattern context;\n     * a spread {@code [...arr, b]} in a regular array literal stays valid.\n     */\n    private static void validateRestElementRules(Node litArray) {\n        int lastArrayElemIdx = -1;\n        for (int i = 0, n = litArray.size(); i < n; i++) {\n            Node ch = litArray.get(i);\n            if (!ch.isToken() && ch.type == NodeType.ARRAY_ELEM) {\n                lastArrayElemIdx = i;\n            }\n        }\n        for (int i = 0, n = litArray.size(); i < n; i++) {\n            Node ch = litArray.get(i);\n            if (ch.isToken() || ch.type != NodeType.ARRAY_ELEM) continue;\n            if (!hasRestPrefix(ch)) continue;\n            if (i != lastArrayElemIdx) {\n                throw new ParserException(\"invalid destructuring: rest element must be the last binding element\");\n            }\n            if (restHasInitializer(ch)) {\n                throw new ParserException(\"invalid destructuring: rest element cannot have an initializer\");\n            }\n        }\n    }\n\n    private static boolean hasRestPrefix(Node arrayElem) {\n        if (arrayElem.size() == 0) return false;\n        Node first = arrayElem.getFirst();\n        return first.isToken() && first.token.type == DOT_DOT_DOT;\n    }\n\n    /**\n     * For an ARRAY_ELEM that starts with {@code ...}, returns true iff the target\n     * expression after the DOT_DOT_DOT carries a top-level assignment — i.e. the\n     * rest target is being given a default value, which is invalid.\n     */","sourceCodeStart":1518,"sourceCodeEnd":1554,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-js/src/main/java/io/karatelabs/parser/JsParser.java#L1518-L1554","documentation":"The Karate JS parser rejects array destructuring patterns where a rest element (`...rest`) is followed by more binding elements. Per spec, `...` must be the final element of an array destructuring pattern. This is a static early error on the literal's parsed ARRAY_ELEM nodes.","triggerScenarios":"Parsing patterns like `[...rest, a] = arr;` or `const [...head, tail] = list;` — the loop flags any rest-prefixed ARRAY_ELEM whose index is not the last array element index.","commonSituations":"Typos where the rest element was typed first; refactoring that reordered destructuring elements; misunderstanding that rest collects 'the remainder' and must come last.","solutions":["Move the `...rest` element to the final position: `[a, b, ...rest]`","Split the destructuring into multiple statements if you need elements after collecting the rest (e.g. `rest[0]`)","Remove the rest element if you only need fixed-position bindings"],"exampleFix":"// before\nconst [...rest, last] = arr;\n// after\nconst [init, ...rest] = arr;\nconst last = rest[rest.length - 1];","handlingStrategy":"validation","validationCode":"// reject patterns where ...rest is not last in an array destructuring\nfunction restNotLast(src) {\n  const m = src.match(/\\[([^\\]]*)\\]\\s*=/);\n  if (!m) return false;\n  const parts = m[1].split(',').map(s => s.trim()).filter(Boolean);\n  const restIdx = parts.findIndex(p => /^\\.\\.\\./.test(p));\n  return restIdx !== -1 && restIdx !== parts.length - 1;\n}","typeGuard":null,"tryCatchPattern":"try {\n  runScript(src);\n} catch (e) {\n  if (String(e).includes('rest element must be the last')) {\n    // reorder destructuring elements\n  }\n  throw e;\n}","preventionTips":["Always place ...rest last in destructuring patterns","Enable ESLint syntax validation on embedded JS snippets","Add unit tests for every destructuring pattern used in feature files"],"tags":["javascript","parser","destructuring","syntax"],"backgroundTag":"invalid-argument-format","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"}