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

  1. Mark the enclosing class `abstract class Foo { ... }`.
  2. Remove the `abstract` modifier and provide a method body.
  3. 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

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


AI-assisted analysis of apple/pkl@f3efcbfc9b (2026-09-08). Data as JSON: /api/errors/fb87e8991952c633. Report an issue: GitHub.