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

  1. Wrap the code in a destructuring context: `const { a = 1 } = obj;` instead of using `{ a = 1 }` as an expression
  2. If you meant a default property value, use a spread or explicit assignment: `{ a: obj.a !== undefined ? obj.a : 1 }` or `{ ...{ a: 1 }, ...obj }`
  3. 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

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


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)