apple/pkl · error · VmTypeMismatchException.Reference

VmTypeMismatchException.Reference (referent type is not a…

Error message

VmTypeMismatchException.Reference (referent type is not a subtype)

What it means

In ReferenceTypeNode.doEval, after the domain check passes, Pkl verifies the reference's referent type via value.referentTypeIsSubtypeOf(...). If the referent type is not a subtype of the declared referent type, it throws VmTypeMismatchException.Reference indicating the reference points at a value of an incompatible type.

Solutions

  1. Make the referenced value an instance of (a subtype of) the declared referent type.
  2. Widen the declared referent type parameter to a common supertype of the actual referents.
  3. Check the exported referent type in the message to see exactly which type was expected.

Example fix

// before
base: Reference<Base> = derived  // derived: Derived, not a subtype of Base
// after
abstract class Base
class Derived extends Base
base: Reference<Base> = derived
Defensive patterns

Strategy: type-guard

Validate before calling

// Pkl: verify referent type before assigning
function checkReferent(r: Reference): Boolean = r.referent is ExpectedType

Type guard

value is Reference<ExpectedType>

Prevention

When it happens

Trigger: A `Reference<T>` (or TypeAlias/constrained reference) is checked where the actual referent's class is not a subtype of T; doEval compares referentTypeNode.doExport() against the value's referent type using thisClass/moduleClass context and throws on failure.

Common situations: Storing a reference to an object of the wrong class; changing a property's declared referent type to a narrower class while existing references still point at the broader type; typealias constraints over references after upstream type changes.

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

Appendix: source

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

      // So `this` can only correspond to the receiver where the type check/annotation is written.
      var thisClass = ((VmClass) getReceiverClassNode.executeGeneric(frame));

      // NB: This will be wrong for deprecated usage of the `module` type in typealias bodies.
      // It will always resolve to the module where the type check/annotation is written
      // not the type itself. This is no _more_ broken than it was before.
      var moduleClass = VmUtils.getClass(getModuleNode.executeGeneric(frame));

      return doEval(value, thisClass, moduleClass);
    }

    @TruffleBoundary
    private Object doEval(VmReference value, VmClass thisClass, VmClass moduleClass) {
      var referentType = referentTypeNode.doExport();
      if (value.referentTypeIsSubtypeOf(referentType, thisClass.export(), moduleClass.export())) {
        return value;
      }

      throw new VmTypeMismatchException.Reference(
          sourceSection, value, domainTypeNode.doExport(), referentType);
    }

    @Fallback
    protected Object fallback(Object value) {
      throw typeMismatch(value, RefModule.getReferenceClass());
    }

    @Override
    protected boolean acceptTypeNode(boolean visitTypeArguments, TypeNodeConsumer consumer) {
      if (visitTypeArguments)
        return consumer.accept(this)
            && consumer.accept(domainTypeNode)
            && consumer.accept(referentTypeNode);
      return consumer.accept(this);
    }

    @Override

View on GitHub (pinned to f3efcbfc9b)