apple/pkl · error · VmTypeMismatchException

type mismatch: value does not conform to declared type (clas

Error message

type mismatch: value does not conform to declared type (class)

What it means

TypeNode.executeLazily checks that a value assigned to a property with a declared class type actually is an instance of that exact class (`VmUtils.getClass(value) == clazz`). If not, it throws a type mismatch stating the value does not conform to the declared type. This enforces Pkl's type annotations on property values.

Source

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

      this.pType = pType;
      this.mirrorFactory = mirrorFactory;
    }

    public static FinalSelfTypeNode moduleType(SourceSection sourceSection, VmClass clazz) {
      return new FinalSelfTypeNode(
          sourceSection, clazz, PType.MODULE, MirrorFactories.moduleTypeFactory);
    }

    public static FinalSelfTypeNode thisType(SourceSection sourceSection, VmClass clazz) {
      return new FinalSelfTypeNode(
          sourceSection, clazz, PType.THIS, MirrorFactories.thisTypeFactory);
    }

    @Override
    protected Object executeLazily(VirtualFrame frame, Object value) {
      if (VmUtils.getClass(value) == clazz) return value;

      throw typeMismatch(value, clazz);
    }

    @Override
    public VmTyped getMirror() {
      return mirrorFactory.create(null);
    }

    @Override
    public boolean doIsEquivalentTo(TypeNode other) {
      if (!(other instanceof FinalSelfTypeNode finalSelfTypeNode)) {
        return false;
      }
      return clazz.equals(finalSelfTypeNode.clazz);
    }

    @Override
    protected PType doExport() {
      return pType;

View on GitHub (pinned to f3efcbfc9b)

Solutions

  1. Assign a value of the exact declared class (create it with the right class)
  2. Check for typos or wrong imports producing a different class
  3. Use a typeconversion or adjust the declared type to a common supertype if intentional

Example fix

// before
server: Server { ... }  // but value is an Endpoint instance
// after
server: Endpoint { ... }  // or construct a Server
Defensive patterns

Strategy: type-guard

Validate before calling

// verify the class of the value matches declared type before assignment
if (value.constructor !== DeclaredClass) throw new Error("value does not conform to declared type");

Type guard

function isExactInstance(v, clazz){ return v != null && Object.getPrototypeOf(v).constructor === clazz; }

Try / catch

try { assign(prop, value); } catch (e) { if (String(e).includes("does not conform")) { /* correct value class and retry */ } else { throw e; } }

Prevention

When it happens

Trigger: Assigning an object of a different (possibly related but not identical) class to a property typed as a specific class; amending a class where the type check expects the exact class; passing a subtype where only the exact class passes this fast path.

Common situations: Confusing similarly named classes; assigning a String where a Number-typed property exists; supplying an untyped dynamic object to a typed property in amends/new expressions.

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