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 != nullView on GitHub (pinned to f3efcbfc9b)
Solutions
- Rename the key or the value identifier so they differ.
- If the key must match the value's name, drop the explicit key and use plain property syntax (`foo = ...`).
- 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
- Prefer plain `name = value` property syntax over explicit `[key]` entries unless keys are dynamic.
- Lint for entries where key text equals bound identifier text.
- After copy-pasting object entries, check identifiers on both sides.
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
- ${errorMessage} This will be an error in a future release.
- classMustBeLocal
- typeAliasMustBeLocal
- nonLocalObjectPropertyCannotHaveTypeAnnotation
- invalidSupertype
AI-assisted analysis of apple/pkl@f3efcbfc9b (2026-09-08).
Data as JSON: /api/errors/d9c18a20f93d1f98.
Report an issue: GitHub.