karatelabs/karate · error · ParserException
invalid destructuring: rest element must be the last…
Error message
invalid destructuring: rest element must be the last binding element
What it means
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.
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
Example fix
// before const [...rest, last] = arr; // after const [init, ...rest] = arr; const last = rest[rest.length - 1];
Defensive patterns
Strategy: validation
Validate before calling
// reject patterns where ...rest is not last in an array destructuring
function restNotLast(src) {
const m = src.match(/\[([^\]]*)\]\s*=/);
if (!m) return false;
const parts = m[1].split(',').map(s => s.trim()).filter(Boolean);
const restIdx = parts.findIndex(p => /^\.\.\./.test(p));
return restIdx !== -1 && restIdx !== parts.length - 1;
} Try / catch
try {
runScript(src);
} catch (e) {
if (String(e).includes('rest element must be the last')) {
// reorder destructuring elements
}
throw e;
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: Typos where the rest element was typed first; refactoring that reordered destructuring elements; misunderstanding that rest collects 'the remainder' and must come last.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- invalid shorthand initializer: only allowed in…
- invalid destructuring: rest element cannot have an…
- invalid
- invalid : parenthesized destructuring pattern
- duplicate binding name
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/915721b3f8e678d4.
Report an issue: GitHub.
Appendix: source
Thrown at karate-js/src/main/java/io/karatelabs/parser/JsParser.java:1536
* AssignmentExpression).</li>
* </ul>
* Called only when the surrounding {@code LIT_ARRAY} is in pattern context;
* a spread {@code [...arr, b]} in a regular array literal stays valid.
*/
private static void validateRestElementRules(Node litArray) {
int lastArrayElemIdx = -1;
for (int i = 0, n = litArray.size(); i < n; i++) {
Node ch = litArray.get(i);
if (!ch.isToken() && ch.type == NodeType.ARRAY_ELEM) {
lastArrayElemIdx = i;
}
}
for (int i = 0, n = litArray.size(); i < n; i++) {
Node ch = litArray.get(i);
if (ch.isToken() || ch.type != NodeType.ARRAY_ELEM) continue;
if (!hasRestPrefix(ch)) continue;
if (i != lastArrayElemIdx) {
throw new ParserException("invalid destructuring: rest element must be the last binding element");
}
if (restHasInitializer(ch)) {
throw new ParserException("invalid destructuring: rest element cannot have an initializer");
}
}
}
private static boolean hasRestPrefix(Node arrayElem) {
if (arrayElem.size() == 0) return false;
Node first = arrayElem.getFirst();
return first.isToken() && first.token.type == DOT_DOT_DOT;
}
/**
* For an ARRAY_ELEM that starts with {@code ...}, returns true iff the target
* expression after the DOT_DOT_DOT carries a top-level assignment — i.e. the
* rest target is being given a default value, which is invalid.
*/View on GitHub (pinned to a22eb90246)