apple/pkl · error · VmException

cannotInstantiateAbstractClass

cannotInstantiateAbstractClass

Error message

cannotInstantiateAbstractClass

What it means

VmUtils.checkIsInstantiable throws 'cannotInstantiateAbstractClass' when code attempts to instantiate a class that is not instantiable (abstract classes, and classes such as base module abstract types). The input at fault is a VmClass with isInstantiable()==false used in an instantiation/new-expression context.

Source

Thrown at pkl-core/src/main/java/org/pkl/core/runtime/VmUtils.java:897

              // another function besides type checking, namely setting frame slot
              new TypeNode.UnknownTypeNode(VmUtils.unavailableSourceSection())
              : unresolvedNode.execute(frame);

      descriptor.setSlotKind(i, typeNode.getFrameSlotKind());
      typeNode.initWriteSlotNode(i);
      resolvedNodes[i] = typeNode;
    }

    return resolvedNodes;
  }

  public static void checkIsInstantiable(VmClass parentClass, @Nullable Node parentNode) {
    if (parentClass.isInstantiable()) return;

    CompilerDirectives.transferToInterpreter();

    if (parentClass.isAbstract()) {
      throw new VmExceptionBuilder()
          .evalError("cannotInstantiateAbstractClass", parentClass)
          .withOptionalLocation(parentNode)
          .build();
    }

    assert parentClass.isExternal();
    throw new VmExceptionBuilder()
        .evalError("cannotInstantiateExternalClass", parentClass)
        .withOptionalLocation(parentNode)
        .build();
  }

  @TruffleBoundary
  public static Pattern compilePattern(String pattern, Node location) {
    try {
      return Pattern.compile(pattern, Pattern.UNICODE_CHARACTER_CLASS | Pattern.UNICODE_CASE);
    } catch (PatternSyntaxException e) {
      throw new VmExceptionBuilder()

View on GitHub (pinned to f3efcbfc9b)

Solutions

  1. Instantiate a concrete subclass instead of the abstract class.
  2. If the intent is a prototype/type reference, use the class itself rather than an instance.

Example fix

// before
val svc = new Service {} // Service is abstract
// after
val svc = new HttpService {} // concrete subclass
Defensive patterns

Strategy: validation

Validate before calling

// at authoring time: only instantiate concrete classes
// if (Class.isAbstract(cls)) throw new Error(cls.name + " is abstract")

Type guard

function isInstantiable(cls) { return !cls.isAbstract && !cls.isExternal; }

Try / catch

try { new Cls {} } catch (e) { /* cannotInstantiateAbstractClass: choose a subclass */ }

Prevention

When it happens

Trigger: `new SomeAbstractClass {}` (or a host call instantiating it) where `parentClass.isAbstract()` is true; typically the user picks a base module/class instead of a concrete subclass.

Common situations: Instantiating a base 'template' class intended only for extension (common in Am tooling and module hierarchies), refactoring that marked a class abstract after subclassing.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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