apple/pkl · error · VmTypeMismatchException

type mismatch: value is not of type Map

Error message

type mismatch: value is not of type Map

What it means

Thrown by the Map type-check node's executeLazily when a value checked against `Map<K,V>` is not a VmMap. Only VmMap instances proceed to the lazy key/value checks; anything else (List, Listing, Set, String, object, null) throws the typeMismatch error naming the `Map` type.

Source

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

    }
  }

  public static final class MapTypeNode extends ObjectSlotTypeNode {
    @Child private TypeNode keyTypeNode;
    @Child private TypeNode valueTypeNode;

    public MapTypeNode(SourceSection sourceSection, TypeNode keyTypeNode, TypeNode valueTypeNode) {
      super(sourceSection);
      this.keyTypeNode = keyTypeNode;
      this.valueTypeNode = valueTypeNode;
    }

    @Override
    protected Object executeLazily(VirtualFrame frame, Object value) {
      if (value instanceof VmMap vmMap) {
        return eval(frame, vmMap);
      }
      throw typeMismatch(value, BaseModule.getMapClass());
    }

    @Override
    public Object executeEagerly(VirtualFrame frame, Object value) {
      if (value instanceof VmMap vmMap) {
        return evalEager(frame, vmMap);
      }
      throw typeMismatch(value, BaseModule.getMapClass());
    }

    @Override
    public Object createDefaultValue(
        VirtualFrame frame,
        VmLanguage language,
        SourceSection headerSection,
        String qualifiedName) {

      return VmMap.EMPTY;

View on GitHub (pinned to f3efcbfc9b)

Solutions

  1. Produce an actual Map: `Map("k", 1, "k2", 2)` or keep the Map instead of extracting entries.
  2. If the value is an object, declare the property as `Mapping` instead of `Map`.
  3. If you called `.entries`/`.keys`/`.values`, use the original map or change the declared type to List.
  4. Convert pairs: `ListPair(...).toMap()` style APIs where available.

Example fix

// before
counts: Map<String, Int> = countsMap.entries // List of pairs
// after
counts: Map<String, Int> = countsMap
Defensive patterns

Strategy: type-guard

Validate before calling

assert(m is Map<String, Int>, "expected Map<String, Int>")

Type guard

function asMap(v): Map<String, Int> = if (v is Map<String, Int>) v else Map()

Prevention

When it happens

Trigger: A lazily-executed `Map<K,V>` constraint receives a non-Map value, e.g. `m: Map<String, Int> = List(1,2)` or assigning a Listing/object to a Map-typed property.

Common situations: Confusing `Map` with `Mapping` (objects with member syntax) or `List`/`Listing`; parsing external YAML/JSON where a key/value block became a list; using `Map(...).entries` result (a List) where the Map itself was expected.

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