apple/pkl · error · VmException

moduleCannotAmendSelf

moduleCannotAmendSelf

Error message

Module `{0}` cannot amend itself.

What it means

A module tried to amend itself, e.g. `module amends` with a reference that resolves back to the same module, or `X` where X is the enclosing module. Self-amendment would create a circular amendment, so Pkl rejects it.

Source

Thrown at pkl-core/src/main/java/org/pkl/core/ast/expression/literal/AmendModuleNode.java:65

  public ModuleInfo getModuleInfo() {
    return moduleInfo;
  }

  @Override
  @TruffleBoundary
  protected AmendModuleNode copy(ExpressionNode newParentNode) {
    throw exceptionBuilder().unreachableCode().build();
  }

  @Specialization
  protected VmTyped eval(VirtualFrame frame, VmTyped supermodule) {
    // receiver is empty module object
    var module = VmUtils.getTypedObjectReceiver(frame);

    if (module == supermodule) {
      CompilerDirectives.transferToInterpreter();
      throw exceptionBuilder()
          .evalError("moduleCannotAmendSelf", moduleInfo.getModuleName())
          .build();
    }

    checkIsValidTypedAmendment(supermodule);

    module.lateInitVmClass(supermodule.getVmClass());
    module.lateInitParent(supermodule);
    module.addProperties(members);

    module.setExtraStorage(moduleInfo);
    moduleInfo.initAnnotations(VmUtils.evaluateAnnotations(frame, annotationNodes));

    return module;
  }
}

View on GitHub (pinned to f3efcbfc9b)

Solutions

  1. Change the amendment target to a different module (e.g. a base/config module).
  2. If extending a module's own output, split into two modules: a base module and an amending module.
  3. Check `amends`/`extends` headers and top-level amend expressions for accidental self-reference.

Example fix

// before (a.pkl amends itself)
amends "a.pkl"
// after
amends "pkl:base" // or a distinct base module
Defensive patterns

Strategy: validation

Validate before calling

// module header must not amend itself
// a.pkl must not contain: amends "a.pkl"

Prevention

When it happens

Trigger: Writing `...myModule` style amendment or `amends`/extend syntax where the supermodule argument equals the module object being evaluated (module == supermodule).

Common situations: Recursive module templates: module `a` amends module `a`, or an amender at the top of a module that amends the module itself instead of a base module.

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/22e201096e304438. Report an issue: GitHub.