apple/pkl · error · VmTypeMismatchException
type mismatch: value is not of type Pair
Error message
type mismatch: value is not of type Pair
What it means
Thrown by PairTypeNode.executeLazily when a lazily-checked value is not a VmPair. The node first typechecks both components of a Pair against its element types; a non-Pair value falls through to this error.
Solutions
- Construct a real Pair with `Pair(first, second)` instead of a list/tuple-like value.
- Verify the value is not null or a differently-shaped collection.
- If the annotation should accept a list, change the type to `Listing`/`List` accordingly.
- Trace the failing property's annotation and align value construction with `Pair(a, b)`.
Example fix
// before p: Pair<Int, Int> = List(1, 2) // after p: Pair<Int, Int> = Pair(1, 2)
Defensive patterns
Strategy: validation
Validate before calling
if (value is Pair) { /* ok */ } else { throw "expected Pair" } Type guard
function isPair(v: Any): Boolean = v is Pair
Prevention
- Always build Pairs with Pair(a, b), not List(a, b).
- Don't interchange List/Listing and Pair types in annotations.
- Guard against nulls reaching Pair-typed properties.
When it happens
Trigger: A value annotated `Pair<X, Y>` receives something that is not a pkl Pair (e.g. a List, Listing, Int, or null) during lazy (speculative/slow-path) evaluation.
Common situations: Using stdlib Pair types in annotations and assigning a two-element Listing or List literal; passing tuples from other languages; building config where a Pair is expected but an array-like value was written.
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
- cannotExportValue
- cannotFlattenCollectionWithNonCollectionElement
- cannotIterateOverThisValue
- cannotSpreadObject
- double
AI-assisted analysis of apple/pkl@f3efcbfc9b (2026-09-08).
Data as JSON: /api/errors/451957908486979c.
Report an issue: GitHub.
Appendix: source
Thrown at pkl-core/src/main/java/org/pkl/core/ast/type/TypeNode.java:2327
public PairTypeNode(
SourceSection sourceSection, TypeNode firstTypeNode, TypeNode secondTypeNode) {
super(sourceSection);
this.firstTypeNode = firstTypeNode;
this.secondTypeNode = secondTypeNode;
}
@Override
protected Object executeLazily(VirtualFrame frame, Object value) {
if (value instanceof VmPair vmPair) {
var first = firstTypeNode.executeLazily(frame, vmPair.getFirst());
var second = secondTypeNode.executeLazily(frame, vmPair.getSecond());
if (first == vmPair.getFirst() && second == vmPair.getSecond()) {
return vmPair;
}
return new VmPair(first, second);
}
throw typeMismatch(value, BaseModule.getPairClass());
}
@Override
public Object executeEagerly(VirtualFrame frame, Object value) {
if (value instanceof VmPair vmPair) {
firstTypeNode.executeEagerly(frame, vmPair.getFirst());
secondTypeNode.executeEagerly(frame, vmPair.getSecond());
return value;
}
throw typeMismatch(value, BaseModule.getPairClass());
}
@Override
public VmClass getVmClass() {
return BaseModule.getPairClass();
}
@OverrideView on GitHub (pinned to f3efcbfc9b)