apple/pkl · error · VmReferenceAccessError
externalClass
Error message
externalClass
What it means
Raised when code references the `output` property of a Module through the Reference property-type machinery. Module.output is defined in an external (base) class, and Pkl forbids referencing properties originally defined in external classes — the only such subclassable case being Module.output.
Source
Thrown at pkl-core/src/main/java/org/pkl/core/runtime/VmReference.java:243
}
// restriction: cannot reference Listing/Mapping.default
if (clazz.getPClass().getInfo() == PClassInfo.Listing
|| clazz.getPClass().getInfo() == PClassInfo.Mapping) {
var errorType =
property.equals("default")
? VmReferenceAccessErrorType.DEFAULT_MEMBER
: VmReferenceAccessErrorType.CANNOT_FIND_MEMBER;
throw new VmReferenceAccessError(type, errorType);
}
var baseModule = BaseModule.getModuleClass().export();
// restriction: cannot reference Module.output.
// generalized: properties originally defined in external classes; the only extant example.
// This is implemented specifically because this is the only case where an external class
// containing a property can be subclassed.
// And this can't check prop.getOwner().isExternal() because fully overriding the property with
// a new type annotation means the owner isn't Module.
if (clazz.getPClass().isSubclassOf(baseModule) && property.equals("output")) {
throw new VmReferenceAccessError(
new PType.Class(baseModule), VmReferenceAccessErrorType.EXTERNAL_CLASS);
}
// dot access on `Reference<D, Null>` gives `Reference<D, Null>`
if (clazz.getPClass().getInfo() == PClassInfo.Null) {
result.add(clazz);
return;
}
var prop = clazz.getPClass().getAllProperties().get(property);
if (prop == null) {
throw new VmReferenceAccessError(type, VmReferenceAccessErrorType.CANNOT_FIND_MEMBER);
}
// restriction: cannot reference external properties
if (prop.isExternal()) {
throw new VmReferenceAccessError(type, VmReferenceAccessErrorType.EXTERNAL_MEMBER);
}View on GitHub (pinned to f3efcbfc9b)
Solutions
- Avoid referencing `module.output` inside Pkl; output is meant for the host/consumer.
- Expose the needed data as a regular (non-output) property on the module.
- If you need the rendered text, evaluate and export from the host side instead.
- Move the data out of `output` into a named property that reference-checking allows.
Example fix
// before x = MyModule.output // after (in MyModule) rendered = "..." // regular property // then x = MyModule.rendered
Defensive patterns
Strategy: validation
Validate before calling
// Pkl: ensure you never reference Module.output in reference positions // expose data as a normal property instead rendered = "..."
Try / catch
try {
eval(src);
} catch (EvalException e) {
if (e.getMessage().contains("externalClass")) {
// you referenced a property from an external class (e.g. Module.output)
}
} Prevention
- Treat `output` as write-only from Pkl's perspective; consume it from the host.
- Duplicate needed output content into a regular property for internal references.
- Avoid building abstractions that read other modules' output.
When it happens
Trigger: Referencing `someModule.output` in a context validated by getCandidatePropertyType (e.g. property type references in amends/extends scenarios).
Common situations: Trying to read another module's rendered output inside Pkl; using `output` in type positions or reference-checking paths rather than through normal evaluation.
Related errors
- cannotExtendExternalClass
- moduleCannotAmendSelf
- cannotHaveRelativeResource
- moduleCannotExtendSelf
- cannotExtendFinalModule
AI-assisted analysis of apple/pkl@f3efcbfc9b (2026-09-08).
Data as JSON: /api/errors/26e1f98a0b2c8894.
Report an issue: GitHub.