apple/pkl · error · VmException
externalMemberCannotHaveBody
externalMemberCannotHaveBody
Error message
externalMemberCannotHaveBody
What it means
A property marked `external` declares its implementation is provided by the host (via externalMemberRegistry) and must not have an inline body. AstBuilder throws externalMemberCannotHaveBody when an external property definition also has `prop = expr`, pointing at the header section.
Source
Thrown at pkl-core/src/main/java/org/pkl/core/ast/builder/AstBuilder.java:2070
var fullModifiers =
doVisitModifiers(
modifierList, VmModifier.VALID_PROPERTY_MODIFIERS, "invalidPropertyModifier");
// for compat, properties may be abstract, but ignore this
var modifiers = fullModifiers & ~VmModifier.ABSTRACT;
var isLocal = VmModifier.isLocal(modifiers);
var propertyName = org.pkl.core.runtime.Identifier.property(name.getValue(), isLocal);
var annotationNodes = doVisitAnnotations(annotations, propertyName);
return symbolTable.enterProperty(
propertyName,
getConstLevel(modifiers),
scope -> {
ExpressionNode bodyNode;
if (expr != null) { // prop = expr
if (VmModifier.isExternal(modifiers)) {
throw exceptionBuilder()
.evalError("externalMemberCannotHaveBody")
.withSourceSection(headerSection)
.build();
}
bodyNode = visitExpr(expr);
} else if (!objectBodies.isEmpty()) { // prop { ... }
if (typeAnnotation != null) {
throw exceptionBuilder()
.evalError("cannotAmendPropertyDefinition")
.withSourceSection(createSourceSection(entry))
.build();
}
bodyNode =
doVisitObjectBody(
objectBodies,
new ReadSuperPropertyNode(
unavailableSourceSection(),
scope.getName(),View on GitHub (pinned to f3efcbfc9b)
Solutions
- Remove the `external` modifier and keep the body.
- Remove the `= expr` body and keep `external`, registering the implementation in the ExternalMemberRegistry.
- Check whether you meant `abstract` (body-less, subclass provides) rather than `external`.
Example fix
// before external prop: Int = 42 // after prop: Int = 42
Defensive patterns
Strategy: validation
Validate before calling
// Ensure external properties have no inline body:
if (hasModifier(prop, "external") && prop.hasValueExpression()) {
report(prop, "external properties cannot have a body");
} Prevention
- Only mark a property `external` when you also register its implementation with the ExternalMemberRegistry.
- External declarations are for host-provided members; user modules rarely need them.
- If you want a body-less method for subclasses, use `abstract`, not `external`.
When it happens
Trigger: Writing `external prop: Type = expr` — i.e. VmModifier.isExternal(modifiers) is true while an expr body is present — during property AST construction.
Common situations: Defining properties that mirror built-in external members of pkl.base modules; hand-writing module code that mimics stdlib declarations; migrating a property from normal to external while leaving its body.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- missingLocalPropertyValue
- ${errorMessage} This will be an error in a future release.
- duplicateDefinition
- classMustBeLocal
- typeAliasMustBeLocal
AI-assisted analysis of apple/pkl@f3efcbfc9b (2026-09-08).
Data as JSON: /api/errors/a860c485d98d1e13.
Report an issue: GitHub.