apple/pkl · error · VmException

duplicateDefinition

duplicateDefinition

Error message

duplicateDefinition

What it means

Pkl throws duplicateDefinition when an object member declares identical key and value identifiers (e.g. a for-generator or property binding where the key name and the bound value name are the same string). The AstBuilder detects this while building the AST because such a definition would shadow itself and is meaningless. The error is raised with the value identifier's source section so the offending identifier is highlighted.

Source

Thrown at pkl-core/src/main/java/org/pkl/core/ast/builder/AstBuilder.java:1587

  public GeneratorMemberNode visitForGenerator(ForGenerator ctx) {

    var keyParameter = ctx.getP2() == null ? null : ctx.getP1();
    var valueParameter = ctx.getP2() == null ? ctx.getP1() : ctx.getP2();
    var keyBinding = makeBinding(keyParameter);
    var valueBinding = makeBinding(valueParameter);
    var keyIdentifier =
        keyParameter instanceof TypedIdentifier keyTypedIdentifier ? keyTypedIdentifier : null;
    var valueIdentifier =
        valueParameter instanceof TypedIdentifier valueTypedIdentifier
            ? valueTypedIdentifier
            : null;
    if (keyIdentifier != null
        && valueIdentifier != null
        && keyIdentifier
            .getIdentifier()
            .getValue()
            .equals(valueIdentifier.getIdentifier().getValue())) {
      throw exceptionBuilder()
          .evalError("duplicateDefinition", valueIdentifier.getIdentifier().getValue())
          .withSourceSection(createSourceSection(valueIdentifier))
          .build();
    }

    var unresolvedKeyTypeNode =
        keyIdentifier == null ? null : visitTypeAnnotation(keyIdentifier.getTypeAnnotation());
    var unresolvedValueTypeNode =
        valueIdentifier == null ? null : visitTypeAnnotation(valueIdentifier.getTypeAnnotation());
    // if possible, initialize immediately to avoid later insert
    var keyTypeNode =
        unresolvedKeyTypeNode == null && keyBinding != null
            ? new TypeNode.UnknownTypeNode(VmUtils.unavailableSourceSection())
                .initWriteSlotNode(keyBinding.slot())
            : null;
    // if possible, initialize immediately to avoid later insert
    var valueTypeNode =
        unresolvedValueTypeNode == null && valueBinding != null

View on GitHub (pinned to f3efcbfc9b)

Solutions

  1. Rename the key or the value identifier so they differ.
  2. If the key must match the value's name, drop the explicit key and use plain property syntax (`foo = ...`).
  3. Search the flagged object body for duplicated identifier text and fix the specific entry reported by the source section.

Example fix

// before
person {
  [name] = name
}
// after
person {
  name = "Alice"
}
Defensive patterns

Strategy: validation

Validate before calling

// Before rendering/parsing an object entry, ensure key and value identifiers differ:
if (key != null && value != null && key.equals(value)) {
  throw new IllegalArgumentException("key and value identifier must differ: " + key);
}

Type guard

boolean isSelfReferential(String key, String value) { return key != null && key.equals(value); }

Prevention

When it happens

Trigger: Declaring an object member or generator entry where keyIdentifier != null && valueIdentifier != null and both identifiers' text is equal (e.g. `[foo] = foo` style bindings) during AST construction in AstBuilder.visitObjectMember-style code.

Common situations: Copy-pasting object entries; writing `for (x in ...) { [x] ... }` where the key equals the loop variable name; hand-editing Pkl config and accidentally repeating the same name on both sides of a definition.

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


AI-assisted analysis of apple/pkl@f3efcbfc9b (2026-09-08). Data as JSON: /api/errors/d9c18a20f93d1f98. Report an issue: GitHub.