apple/pkl · error · VmTypeMismatchException.ClassType

VmTypeMismatchException.ClassType (type argument is not a va

Error message

VmTypeMismatchException.ClassType (type argument is not a valid class type)

What it means

ClassClassTypeNode checks values typed as `Class<T>` (a Pkl class object). After resolving the expected class from the type argument, if the resolved class is null — meaning the type argument is not a valid, concrete class type (e.g. a typealias to a non-class, union, or unknown/parametric type that could not be reduced) — it throws VmTypeMismatchException.ClassType with the exported type argument.

Source

Thrown at pkl-core/src/main/java/org/pkl/core/ast/type/TypeNode.java:3277

      return BaseModule.getClassClass();
    }

    @Specialization
    protected Object eval(VmClass value) {
      // safe to init clazz here (instead of on init and typealias instantiate)
      // because in the typealias case this node will never execute prior to instantiation
      initVmClass();

      // Fast path: all classes match Class<Any> / Class<unknown> / Class<type arg>.
      // In this case, skip the subclass check and behave like a bare `Class` type annotation.
      if (clazz == BaseModule.getAnyClass()) {
        return value;
      }

      // clazz will be null iff the type arg is a not a valid class type
      if (clazz == null) {
        CompilerDirectives.transferToInterpreter();
        throw new VmTypeMismatchException.ClassType(sourceSection, value, typeNode.doExport());
      }

      if (!value.isSubclassOf(clazz)) {
        CompilerDirectives.transferToInterpreter();
        throw new VmTypeMismatchException.ClassType(sourceSection, value, clazz);
      }

      return value;
    }

    @Fallback
    protected Object fallback(Object value) {
      throw typeMismatch(value, BaseModule.getClassClass());
    }

    @Override
    protected boolean acceptTypeNode(boolean visitTypeArguments, TypeNodeConsumer consumer) {
      if (visitTypeArguments) {

View on GitHub (pinned to f3efcbfc9b)

Solutions

  1. Use a concrete class as the type argument (e.g. `Class<Foo>`, or `Class<Any>` for any class).
  2. If using a typealias, make it alias a single class type.
  3. Handle parametric/type-variable arguments by declaring them as `Class<unknown>`-compatible or resolving them at instantiation.

Example fix

// before
alias FooOrBar = Foo | Bar
k: Class<FooOrBar> = Foo
// after
k: Class<Foo> = Foo
Defensive patterns

Strategy: type-guard

Validate before calling

// Pkl: only concrete classes are valid Class<T> arguments
k: Class<Foo> = Foo  // not Class<SomeUnion> or an unresolved type variable

Type guard

value is Class

Prevention

When it happens

Trigger: A `Class<...>` type annotation whose type argument is not a valid class type: the argument is a union, a typealias that does not reduce to a class, or a type variable that cannot be resolved; then a VmClass value is checked against it.

Common situations: Passing `Class<SomeUnion>` or `Class<SomeTypeAlias>` where the alias/union doesn't denote a single class; generic code taking `Class<T>` with an unresolved T; refactoring a typealias that previously aliased a class into a constrained/union type.

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/8e0f3144d5f22049. Report an issue: GitHub.