karatelabs/karate · error · ParserException
invalid shorthand initializer: only allowed in…
Error message
invalid shorthand initializer: only allowed in destructuring pattern
What it means
Karate's JS parser implements ES2015+ early errors: a shorthand object property with an initializer ({a = 1}) is only legal inside a destructuring pattern. When the parser finds such a form in a normal object literal (assignment/expression context), it throws this ParserException immediately after building the node. This mirrors V8's "Shorthand property assignments are valid only within destructuring patterns".
Solutions
- Wrap the code in a destructuring context: `const { a = 1 } = obj;` instead of using `{ a = 1 }` as an expression
- If you meant a default property value, use a spread or explicit assignment: `{ a: obj.a !== undefined ? obj.a : 1 }` or `{ ...{ a: 1 }, ...obj }`
- Check for brace mismatches (e.g. in Karate feature-file embedded JS) that make a destructuring pattern look like an object literal
Example fix
// before
const a = { b = 1 };
// after
const { b = 1 } = obj; Defensive patterns
Strategy: validation
Validate before calling
// Only use `=` defaults inside destructuring patterns:
const ok = /const\s*\{|let\s*\{|var\s*\{|=\s*\[|^\s*\(\s*\{/.test(src); // heuristic — ensure {a = 1} appears only after const/let/var or a call target Prevention
- Reserve `=` defaults for destructuring declarations only
- Lint embedded feature-file JS for `{ ident = ` outside const/let/var
- Double-check brace pairing when JS is embedded in Karate feature files
When it happens
Trigger: Writing an object literal like `({ a = 1 })` or `({ a = 1, b })` where `{a = 1}` is parsed as an OBJECT_ELEM with a cover-initialization form while the parser's `inPattern` flag is false — i.e. the code appears in a plain expression, argument, or return value rather than the target of a destructuring assignment or declaration.
Common situations: Typos when intending destructuring (writing `const {a = 1}` as `const a = {b = 2}`), hand-written Karate JS embedded in feature files where `{}` braces conflict with the surrounding syntax, or porting code that relied on sloppy non-standard parser behavior.
Related errors
- invalid destructuring: rest element must be the last…
- 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/5ce9a8f4524ffbf1.
Report an issue: GitHub.
Appendix: source
Thrown at karate-js/src/main/java/io/karatelabs/parser/JsParser.java:214
* always null unless the file used a label) — and recomputes each for the children. The
* per-node check bodies live in dedicated helpers so this stays the one place
* the tree is walked; a new early-error rule plugs in as another helper call,
* not another traversal.
* <p>
* Per-node check order mirrors the former pass order
* (assignment-target/decl-position → CoverInitializedName → strict-mode) so a
* node that could trip more than one rule reports the same message as before.
*/
private void earlyErrors(Node node, boolean strict, boolean inPattern, PrivateScope privates, Label labels) {
if (node == null) {
return;
}
// Mode-independent: assignment-target validity, optional-chain restrictions,
// declaration-in-statement-position.
earlyErrorNodeChecks(node);
// CoverInitializedName / rest-element rules, gated on pattern context.
if (node.type == NodeType.OBJECT_ELEM && hasCoverInitForm(node) && !inPattern) {
throw new ParserException("invalid shorthand initializer: only allowed in destructuring pattern");
}
if (inPattern && node.type == NodeType.LIT_ARRAY) {
validateRestElementRules(node);
}
// §15.7.1 static-block family — scans only the block's own subtree.
if (node.type == NodeType.CLASS_STATIC_BLOCK) {
checkStaticBlockBody(node, 0);
}
// At most one B.3.1 proto-setter per ObjectLiteral; not a rule for patterns.
if (sawProtoKey && !inPattern && node.type == NodeType.LIT_OBJECT) {
checkNoDuplicateProtoSetter(node);
}
// Private-name family; returns the private scope to propagate to children.
PrivateScope childPrivates = sawPrivateName ? privateNodeChecks(node, privates) : privates;
// Strict-mode family; returns the strictness to propagate to children.
boolean childStrict = strictNodeChecks(node, strict);
// Label family; returns the label chain to propagate to children.
Label childLabels = sawLabel ? labelNodeChecks(node, labels) : null;View on GitHub (pinned to a22eb90246)