apple/pkl · error
redundantOpenModifier
redundantOpenModifier
Error message
redundantOpenModifier
What it means
`abstract` and `open` are mutually exclusive class modifiers in Pkl: `abstract` forbids instantiation, `open` allows external amendment. Combining them is contradictory, so AstBuilder throws `redundantOpenModifier` pointing at the OPEN modifier (AstBuilder.java:3030).
Source
Thrown at pkl-core/src/main/java/org/pkl/core/ast/builder/AstBuilder.java:3030
.build();
}
if (VmModifier.isLocal(result) && VmModifier.isHidden(result)) {
throw exceptionBuilder()
.evalError("redundantHiddenModifier")
.withSourceSection(createSourceSection(modifiers, ModifierValue.HIDDEN))
.build();
}
if (VmModifier.isLocal(result) && VmModifier.isFixed(result)) {
throw exceptionBuilder()
.evalError("redundantFixedModifier")
.withSourceSection(createSourceSection(modifiers, ModifierValue.FIXED))
.build();
}
if (VmModifier.isAbstract(result) && VmModifier.isOpen(result)) {
throw exceptionBuilder()
.evalError("redundantOpenModifier")
.withSourceSection(createSourceSection(modifiers, ModifierValue.OPEN))
.build();
}
return result;
}
private UnresolvedTypeNode[] doVisitParameterTypes(ObjectBody body) {
return doVisitParameterTypes(body.getParameters());
}
private UnresolvedTypeNode[] doVisitParameterTypes(ParameterList paramList) {
return doVisitParameterTypes(paramList.getParameters());
}
private UnresolvedTypeNode[] doVisitParameterTypes(List<org.pkl.parser.syntax.Parameter> params) {
var typeNodes = new UnresolvedTypeNode[params.size()];View on GitHub (pinned to f3efcbfc9b)
Solutions
- Decide semantics: keep `abstract` (instantiation forbidden, must extend) or `open` (amendable), not both.
- In Pkl classes are effectively open to amendments already; usually just remove `open` from the abstract class.
- Split into an abstract base and an open subclass if both behaviors are needed.
Example fix
// before
abstract open class Foo {}
// after
abstract class Foo {} Defensive patterns
Strategy: validation
Validate before calling
if (/abstract\s+open\s+class|open\s+abstract\s+class/.test(pklSource)) {
throw new Error("`abstract` and `open` are mutually exclusive class modifiers");
} Prevention
- Decide up front whether a class is a template (abstract) or an amendable default (open).
- Note that Pkl classes are amendable by default; `open` is rarely needed.
- Keep class declarations to at most one of abstract/open.
When it happens
Trigger: Declaring `abstract open class Foo {}` in a module.
Common situations: Copying modifier lists from multiple class declarations; unclear whether a class should be extensible or abstract, so both modifiers were kept.
Related errors
- moduleMethodMustBeLocal
- invalidObjectMemberModifier
- redundantHiddenModifier
- redundantFixedModifier
- Cannot parse `%s` as number.
AI-assisted analysis of apple/pkl@f3efcbfc9b (2026-09-08).
Data as JSON: /api/errors/dd20482240332143.
Report an issue: GitHub.