apple/pkl · error · VmException
abstractMethodInNonAbstractType
abstractMethodInNonAbstractType
Error message
abstractMethodInNonAbstractType
What it means
Abstract methods may only appear inside abstract classes/types. AstBuilder's check raises abstractMethodInNonAbstractType with the offending `abstract` modifier span when the enclosing type lacks the `abstract` modifier but any method in it declares `abstract`. This keeps the runtime from ever needing to dispatch to a body-less method on a concrete type.
Source
Thrown at pkl-core/src/main/java/org/pkl/core/ast/builder/AstBuilder.java:2002
case EXTERNAL -> VmModifier.EXTERNAL;
case ABSTRACT -> VmModifier.ABSTRACT;
case OPEN -> VmModifier.OPEN;
case LOCAL -> VmModifier.LOCAL;
case HIDDEN -> VmModifier.HIDDEN;
case FIXED -> VmModifier.FIXED;
case CONST -> VmModifier.CONST;
};
}
private void checkAbstractMethodsAllowed(
int enclosingModifiers, List<ClassMethod> methods, String context) {
if (VmModifier.isAbstract(enclosingModifiers)) {
return;
}
for (var method : methods) {
for (var modifier : method.getModifiers()) {
if (modifier.getValue() == ModifierValue.ABSTRACT) {
throw exceptionBuilder()
.evalError("abstractMethodInNonAbstractType", context)
.withSourceSection(createSourceSection(modifier.span()))
.build();
}
}
}
}
private UnresolvedPropertyNode[] doVisitClassProperties(
List<ClassProperty> propertyContexts, Set<String> propertyNames) {
var propertyNodes = new UnresolvedPropertyNode[propertyContexts.size()];
for (var i = 0; i < propertyNodes.length; i++) {
var propertyNode = visitClassProperty(propertyContexts.get(i));
checkDuplicateMember(propertyNode.getName(), propertyNode.getHeaderSection(), propertyNames);
propertyNodes[i] = propertyNode;
}
View on GitHub (pinned to f3efcbfc9b)
Solutions
- Mark the enclosing class `abstract class Foo { ... }`.
- Remove the `abstract` modifier and provide a method body.
- Move the abstract method to an abstract superclass.
Example fix
// before
class Animal {
abstract speak(): String
}
// after
abstract class Animal {
abstract speak(): String
} Defensive patterns
Strategy: validation
Validate before calling
// Flag abstract methods inside non-abstract classes:
if (!classDeclaresAbstract && methodBody.matches("\\s*abstract\\s+.*")) {
report(file, lineNo, "abstract method requires abstract enclosing class");
} Prevention
- Pair every `abstract` method with an `abstract class` declaration.
- Only copy abstract signatures into abstract classes.
- Prefer providing a default body in concrete classes instead of abstract methods.
When it happens
Trigger: Declaring `abstract foo(): Unknown` inside a non-abstract `class Foo { ... }`; adding the abstract modifier to a method while forgetting to mark the enclosing class abstract.
Common situations: Refactoring a concrete class toward an interface-like shape; copying method signatures from an abstract base class into a concrete subclass.
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
- classMustBeLocal
- cannotExtendExternalClass
- ${errorMessage} This will be an error in a future release.
- duplicateDefinition
- typeAliasMustBeLocal
AI-assisted analysis of apple/pkl@f3efcbfc9b (2026-09-08).
Data as JSON: /api/errors/fb87e8991952c633.
Report an issue: GitHub.