apple/pkl · error

classCannotExtendSelf

classCannotExtendSelf

Error message

classCannotExtendSelf

What it means

Pkl throws classCannotExtendSelf when a class's `extends` clause resolves to the class being defined. ClassNode.checkSupertype (non-module branch) compares the cached class with the resolved superclass and rejects direct self-inheritance. Self-extension would be a trivially infinite inheritance loop, so it fails immediately at class definition.

Source

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

          .withSourceSection(supertypeNode.getSourceSection())
          .build();
    }
    if (moduleInfo != null) {
      if (cachedClass == superclass) {
        throw exceptionBuilder()
            .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 or correct the `extends` clause so it names a different superclass.
  2. Extend the intended base class instead of the class itself.
  3. Fix the code generator/templating variable that emits the class's own name as its supertype.
  4. If no inheritance is needed, delete the extends clause entirely.

Example fix

// before
class Server extends Server {}

// after
class Server extends BaseServer {}
Defensive patterns

Strategy: validation

Validate before calling

// Ensure class name and extends name differ; lint or review generated Pkl:
// bad: class Server extends Server {}
// pkl eval classes.pkl fails immediately with classCannotExtendSelf.

Prevention

When it happens

Trigger: Writing `class Foo extends Foo`; a template/render step substituting the class's own name into its supertype slot; a generated Pkl file where generator output names the same class on both sides.

Common situations: Code-generation templates with a wrong placeholder; copy-pasting a class declaration and updating the name but not the extends clause; macro-like templating in build tooling resolving to the same identifier.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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