apple/pkl · error · VmException

notASubclassOfTyped

notASubclassOfTyped

Error message

notASubclassOfTyped

What it means

DynamicNodes' `toTyped` method converts a Dynamic object into an instance of a given Pkl class. The argument must be a class that is a subclass of `Typed` (the base of all typed object classes); otherwise it throws `notASubclassOfTyped`. Classes like Module, List, Map or user classes not extending Typed cannot be used as conversion targets.

Source

Thrown at pkl-core/src/main/java/org/pkl/core/stdlib/base/DynamicNodes.java:101

    protected VmList eval(VmDynamic self) {
      var builder = VmList.EMPTY.builder();
      self.forceAndIterateMemberValues( // could be smarter and only force elements
          (key, member, value) -> {
            if (member.isElement()) {
              builder.add(value);
            }
            return true;
          });
      return builder.build();
    }
  }

  public abstract static class toTyped extends ExternalMethod1Node {
    @Specialization
    protected VmObjectLike eval(VmDynamic self, VmClass clazz) {
      if (!clazz.isSubclassOf(BaseModule.getTypedClass())) {
        CompilerDirectives.transferToInterpreter();
        throw exceptionBuilder().evalError("notASubclassOfTyped", clazz).build();
      }

      VmUtils.checkIsInstantiable(clazz, this);

      var result =
          new VmTyped(
              VmUtils.createEmptyMaterializedFrame(),
              clazz.getPrototype(),
              clazz,
              clazz.getDynamicToTypedMembers());
      result.setExtraStorage(self);
      return result;
    }
  }
}

View on GitHub (pinned to f3efcbfc9b)

Solutions

  1. Pass a class declared with properties (a typed class) that implicitly subclasses `Typed`, e.g. `dynamic.toTyped(MyConfig)`.
  2. Verify the argument is a class value (lowercase `Class` reference, not an instance or module).
  3. If the target is a module, use module-appropriate conversion instead of `toTyped`.
  4. Check that the class was not refactored into a non-Typed base class.

Example fix

// before
typed = dynamic.toTyped(Listing)  // Listing is not a subclass of Typed
// after
typed = dynamic.toTyped(MyConfigClass)  // a typed class
Defensive patterns

Strategy: type-guard

Type guard

// Pkl: only call toTyped with typed classes
function canToTyped(clazz) = clazz.isSubclassOf(Typed)

Prevention

When it happens

Trigger: Calling `dynamic.toTyped(SomeClass)` (DynamicNodes.java:101) where SomeClass is a Pkl class not derived from `Typed` — e.g. passing `Int`, `Listing`, `Module`, or an annotation/interface-like class.

Common situations: Mixing up class references when converting dynamic config (passing a module class instead of a typed class), refactoring that replaced a typed class with an untyped base, or generic helper code that accepts any `Class` value.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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