karatelabs/karate · error · ParserException

duplicate binding name

Error message

duplicate binding name '${name}' is not allowed in a catch parameter

What it means

A `catch (pattern)` binding may not contain duplicate names. Karate collects every bound name in the catch parameter (including destructured bindings like `catch ({e, e})`) and rejects duplicates, per the ECMAScript CatchParameter uniqueness rule.

Solutions

  1. Remove or rename the duplicated binding in the catch pattern.
  2. If both sources are needed, alias one: `catch ({message: msg1, message: msg2})` — wait, that is still the same key; instead bind once and derive the second value in the body.
  3. If the pattern was accidentally duplicated, simplify to a single binding: `catch (e) { const { message } = e; }`.

Example fix

// before
try { risky(); } catch ({ message, message }) { log(message); }
// after
try { risky(); } catch (err) { log(err.message); }
Defensive patterns

Strategy: validation

Validate before calling

function assertUniqueCatchBinding(catchSrc) {
  const inner = catchSrc.slice(catchSrc.indexOf('(') + 1, catchSrc.lastIndexOf(')'));
  const names = inner.match(/[\w$]+/g) || [];
  const seen = new Set();
  for (const n of names) {
    if (seen.has(n)) throw new Error('duplicate catch binding: ' + n);
    seen.add(n);
  }
}

Try / catch

try {
  karate.eval(script);
} catch (e) {
  if (String(e.message).includes("not allowed in a catch parameter")) {
    // simplify the catch pattern to a single binding
  } else throw e;
}

Prevention

When it happens

Trigger: Writing `try {} catch (e, ...)` is impossible in JS, but `catch (e) ` duplication arises via destructuring: `catch ({message, message}) {}` or array patterns like `catch ([x, x]) {}` in Karate JS.

Common situations: Copy-paste errors in destructured catch clauses; merging bindings from two sources into one pattern without noticing the collision; code-generation templates producing duplicated keys.

Understand the failure class

Background: "must be a positive integer", "cannot be empty", "invalid argument": how invalid-argument errors work across open-source libraries — this error's family across 33 libraries.

Related errors


AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12). Data as JSON: /api/errors/f21fdaf45bb82cbf. Report an issue: GitHub.

Appendix: source

Thrown at karate-js/src/main/java/io/karatelabs/parser/JsParser.java:1127

                }
                if (ch.token.type == IDENT) {
                    binding = ch; // simple catch binding — no duplicate possible
                    break;
                }
                // skip the L_PAREN
            } else {
                binding = ch; // LIT_ARRAY / LIT_OBJECT pattern
                break;
            }
        }
        if (binding == null) {
            return;
        }
        List<String> names = new ArrayList<>();
        collectBoundNames(binding, names);
        String dup = firstDuplicate(names);
        if (dup != null) {
            throw new ParserException(
                    "duplicate binding name '" + dup + "' is not allowed in a catch parameter");
        }
        if (strict) {
            for (String name : names) {
                if (isEvalOrArguments(name)) {
                    throw new ParserException(
                            "'" + name + "' is not a valid binding name in strict mode");
                }
            }
        }
    }

    /** A strict var/let/const declaration may not bind {@code eval} / {@code arguments}
     *  — including inside a destructuring pattern. (Lexical duplicate-BoundNames for
     *  let/const patterns is a distinct rule, deferred — VAR_DECL doesn't carry the
     *  let-vs-var distinction.) */
    private static void checkVarDeclName(Node varDecl) {
        List<String> names = new ArrayList<>();

View on GitHub (pinned to a22eb90246)