{"record":{"id":"dd20482240332143","repo":"apple/pkl","slug":"redundantopenmodifier","errorCode":"redundantOpenModifier","errorMessage":"redundantOpenModifier","messagePattern":"redundantOpenModifier","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkl-core/src/main/java/org/pkl/core/ast/builder/AstBuilder.java","lineNumber":3030,"sourceCode":"          .build();\n    }\n\n    if (VmModifier.isLocal(result) && VmModifier.isHidden(result)) {\n      throw exceptionBuilder()\n          .evalError(\"redundantHiddenModifier\")\n          .withSourceSection(createSourceSection(modifiers, ModifierValue.HIDDEN))\n          .build();\n    }\n\n    if (VmModifier.isLocal(result) && VmModifier.isFixed(result)) {\n      throw exceptionBuilder()\n          .evalError(\"redundantFixedModifier\")\n          .withSourceSection(createSourceSection(modifiers, ModifierValue.FIXED))\n          .build();\n    }\n\n    if (VmModifier.isAbstract(result) && VmModifier.isOpen(result)) {\n      throw exceptionBuilder()\n          .evalError(\"redundantOpenModifier\")\n          .withSourceSection(createSourceSection(modifiers, ModifierValue.OPEN))\n          .build();\n    }\n\n    return result;\n  }\n\n  private UnresolvedTypeNode[] doVisitParameterTypes(ObjectBody body) {\n    return doVisitParameterTypes(body.getParameters());\n  }\n\n  private UnresolvedTypeNode[] doVisitParameterTypes(ParameterList paramList) {\n    return doVisitParameterTypes(paramList.getParameters());\n  }\n\n  private UnresolvedTypeNode[] doVisitParameterTypes(List<org.pkl.parser.syntax.Parameter> params) {\n    var typeNodes = new UnresolvedTypeNode[params.size()];","sourceCodeStart":3012,"sourceCodeEnd":3048,"githubUrl":"https://github.com/apple/pkl/blob/f3efcbfc9b60d30053b0536d664948d7aa1b8673/pkl-core/src/main/java/org/pkl/core/ast/builder/AstBuilder.java#L3012-L3048","documentation":"`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).","triggerScenarios":"Declaring `abstract open class Foo {}` in a module.","commonSituations":"Copying modifier lists from multiple class declarations; unclear whether a class should be extensible or abstract, so both modifiers were kept.","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."],"exampleFix":"// before\nabstract open class Foo {}\n// after\nabstract class Foo {}","handlingStrategy":"validation","validationCode":"if (/abstract\\s+open\\s+class|open\\s+abstract\\s+class/.test(pklSource)) {\n  throw new Error(\"`abstract` and `open` are mutually exclusive class modifiers\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["pkl","parser","modifier","class-declaration"],"backgroundTag":"mutually-exclusive-options","analyzedSha":"f3efcbfc9b60d30053b0536d664948d7aa1b8673","analyzedAt":"2026-09-08T13:10:45.570Z","contentChangedAt":"2026-09-08T13:10:45.570Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}