apple/pkl · error

cannotExtendFinalClass

cannotExtendFinalClass

Error message

cannotExtendFinalClass

What it means

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.

Source

Thrown at pkl-core/src/main/java/org/pkl/core/ast/member/ClassNode.java:195

            .evalError("moduleCannotExtendSelf", moduleInfo.getModuleName())
            .withSourceSection(supertypeNode.getSourceSection())
            .build();
      }
      if (superclass.isClosed()) {
        throw exceptionBuilder()
            .evalError("cannotExtendFinalModule", superclass.getModuleName())
            .withSourceSection(supertypeNode.getSourceSection())
            .build();
      }
    } else {
      if (cachedClass == superclass) {
        throw exceptionBuilder()
            .evalError("classCannotExtendSelf", superclass.getDisplayName())
            .withSourceSection(supertypeNode.getSourceSection())
            .build();
      }
      if (superclass.isClosed()) {
        throw exceptionBuilder()
            .evalError("cannotExtendFinalClass", superclass.getDisplayName())
            .withSourceSection(supertypeNode.getSourceSection())
            .build();
      }
      if (superclass.isExternal() && !classInfo.isStandardLibraryClass()) {
        throw new VmExceptionBuilder()
            .evalError("cannotExtendExternalClass", superclass.getDisplayName())
            .withSourceSection(supertypeNode.getSourceSection())
            .build();
      }
    }
  }
}

View on GitHub (pinned to f3efcbfc9b)

Solutions

  1. Remove the extends clause and use composition instead of inheritance.
  2. Use an object literal (`new`) or amending (`...`) to customize instances rather than subclassing.
  3. If the class is your own, drop the `closed` modifier to allow extension.
  4. For stdlib classes, wrap or convert values rather than extending them.

Example fix

// before
class MyString extends String {}

// after
import "pkl:base"
myStr = ("prefix" + someBase) // compose instead of extend
Defensive patterns

Strategy: validation

Validate before calling

// Before extending, confirm the superclass is neither closed nor external:
// avoid `extends String` / extends any class declared `closed class ...`
// pkl eval fails at class definition with cannotExtendFinalClass.

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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