{"record":{"id":"3dee025ed7b3162a","repo":"apple/pkl","slug":"cannotextendfinalclass","errorCode":"cannotExtendFinalClass","errorMessage":"cannotExtendFinalClass","messagePattern":"cannotExtendFinalClass","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkl-core/src/main/java/org/pkl/core/ast/member/ClassNode.java","lineNumber":195,"sourceCode":"            .evalError(\"moduleCannotExtendSelf\", moduleInfo.getModuleName())\n            .withSourceSection(supertypeNode.getSourceSection())\n            .build();\n      }\n      if (superclass.isClosed()) {\n        throw exceptionBuilder()\n            .evalError(\"cannotExtendFinalModule\", superclass.getModuleName())\n            .withSourceSection(supertypeNode.getSourceSection())\n            .build();\n      }\n    } else {\n      if (cachedClass == superclass) {\n        throw exceptionBuilder()\n            .evalError(\"classCannotExtendSelf\", superclass.getDisplayName())\n            .withSourceSection(supertypeNode.getSourceSection())\n            .build();\n      }\n      if (superclass.isClosed()) {\n        throw exceptionBuilder()\n            .evalError(\"cannotExtendFinalClass\", superclass.getDisplayName())\n            .withSourceSection(supertypeNode.getSourceSection())\n            .build();\n      }\n      if (superclass.isExternal() && !classInfo.isStandardLibraryClass()) {\n        throw new VmExceptionBuilder()\n            .evalError(\"cannotExtendExternalClass\", superclass.getDisplayName())\n            .withSourceSection(supertypeNode.getSourceSection())\n            .build();\n      }\n    }\n  }\n}\n","sourceCodeStart":177,"sourceCodeEnd":209,"githubUrl":"https://github.com/apple/pkl/blob/f3efcbfc9b60d30053b0536d664948d7aa1b8673/pkl-core/src/main/java/org/pkl/core/ast/member/ClassNode.java#L177-L209","documentation":"Pkl throws cannotExtendFinalClass when a class declares `extends` on a class marked `closed`/final (isClosed() true) in the non-module branch of checkSupertype. Final classes forbid subclassing to preserve invariants, so the declaration is rejected with the final class's display name. External (standard-library) classes are likewise barred unless the extender is itself a standard-library class.","triggerScenarios":"Extending a class declared `closed` in user or library code; extending an external/standard-library class (isExternal) from non-standard-library code; a library release that closed a previously open class.","commonSituations":"Trying to subclass String/List-like stdlib classes; extending a framework class that was made final for safety; upgrading a dependency whose classes are now closed, breaking previously valid Pkl code.","solutions":["Remove the extends clause and use composition instead of inheritance.","Use an object literal (`new`) or amending (`...`) to customize instances rather than subclassing.","If the class is your own, drop the `closed` modifier to allow extension.","For stdlib classes, wrap or convert values rather than extending them."],"exampleFix":"// before\nclass MyString extends String {}\n\n// after\nimport \"pkl:base\"\nmyStr = (\"prefix\" + someBase) // compose instead of extend","handlingStrategy":"validation","validationCode":"// Before extending, confirm the superclass is neither closed nor external:\n// avoid `extends String` / extends any class declared `closed class ...`\n// pkl eval fails at class definition with cannotExtendFinalClass.","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never extend standard-library classes; wrap or convert values instead.","Look for `closed` on a class before writing extends.","Use `new` object literals or amend (`...`) to customize instances.","Track library upgrades where classes become closed."],"tags":["pkl","inheritance","final-class","class"],"backgroundTag":"unsupported-operation","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"}