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
- Change the amendment target to a different module (e.g. a base/config module).
- If extending a module's own output, split into two modules: a base module and an amending module.
- 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
- Review `amends`/`extends` headers for self-references.
- Split self-extending modules into base + amender modules.
- Check top-level amend expressions for accidental receiver == supermodule.
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
- externalClass
- cannotHaveRelativeResource
- moduleCannotExtendSelf
- cannotExtendFinalModule
- classCannotExtendSelf
AI-assisted analysis of apple/pkl@f3efcbfc9b (2026-09-08).
Data as JSON: /api/errors/22e201096e304438.
Report an issue: GitHub.