apple/pkl · error · VmTypeMismatchException
type mismatch: value's class differs from expected class
Error message
type mismatch: value's class differs from expected class
What it means
Pkl exact-class type check failure. This node checks `clazz == vmValue.getVmClass()` — the value's class must be exactly the expected final class (no subclassing allowed, because the class is final). The value was a VmValue but its runtime class differed from the expected one.
Source
Thrown at pkl-core/src/main/java/org/pkl/core/ast/type/TypeNode.java:724
/**
* A non-open and non-abstract class type. Since this node is not used for
* String/Boolean/Int/Float and their supertypes, only `VmValue`s can possibly pass its type
* check.
*/
public static final class FinalClassTypeNode extends ObjectSlotTypeNode
implements UserClassTypeNode {
private final VmClass clazz;
public FinalClassTypeNode(SourceSection sourceSection, VmClass clazz) {
super(sourceSection);
this.clazz = clazz;
}
@Override
protected Object executeLazily(VirtualFrame frame, Object value) {
if (value instanceof VmValue vmValue && clazz == vmValue.getVmClass()) return value;
throw typeMismatch(value, clazz);
}
@Override
public VmClass getVmClass() {
return clazz;
}
@Override
public VmList getTypeArgumentMirrors() {
// `List<X>` is represented by `ListTypeNode`,
// but `List` is represented by `FinalClassTypeNode`
return createUnknownTypeArgumentMirrors(clazz);
}
@Override
public @Nullable Object createDefaultValue(
VirtualFrame frame,
VmLanguage language,View on GitHub (pinned to f3efcbfc9b)
Solutions
- Convert the value to the exact expected class (e.g. `value.toInt()`, `value.toList()`, `Double(...)`).
- If several classes are acceptable, declare a union type (`Int | Float`).
- Check the declared type at the error position and make the producer return that exact class.
- Avoid implicit numeric widening assumptions — Pkl does not coerce between number classes.
Example fix
// before x: Int = 1.5 // after x: Int = 1.5.toInt() // or declare `x: Float`
Defensive patterns
Strategy: type-guard
Validate before calling
// Pkl
if (value is Int) { x: Int = value } else if (value is Float) { x: Int = value.toInt() } Type guard
function isExactInt(value: Any): Boolean = value is Int
Try / catch
// Convert explicitly (toInt()/toList()/etc.) before assignment; embedders: catch PklException with 'class differs from expected class'.
Prevention
- Pkl never coerces between final classes — always convert explicitly
- Watch numeric literals: 1 vs 1.0 are different classes
- Declare union types when sibling classes are acceptable
When it happens
Trigger: Assigning an instance of a different (final) class than declared, e.g. declaring `IntSeq`-like or other final VmValue class types (Int8/UInt16/List/etc.) and passing a sibling type such as assigning an `Int` where `Int32`... class-exact types are enforced; passing a Float where Int is required.
Common situations: Numeric type confusion (Int vs Float, Int8 vs Int), passing a List where a Set (or similar final collection class) is declared, or declaring a concrete final class and receiving a subclass/other class instance from a library.
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
- type mismatch: value does not conform to declared type (clas
- type mismatch: value's class is not a subclass of expected c
- type mismatch: value is not the expected string literal
- type mismatch: value is not of type Typed
- type mismatch: value is not of type Dynamic
AI-assisted analysis of apple/pkl@f3efcbfc9b (2026-09-08).
Data as JSON: /api/errors/1cda57cccc4b1e9f.
Report an issue: GitHub.