apple/pkl · error · VmTypeMismatchException

type mismatch: value is not of type Set

Error message

type mismatch: value is not of type Set

What it means

Thrown from the Set type-check node's @Fallback method: when the specialized set-execution fragments do not match (i.e. the value is not a VmSet), the fallback throws a typeMismatch against the `Set` class. It means a value checked against `Set<T>` (or `c Set` shorthand) is not a Pkl Set.

Solutions

  1. Convert the List to a Set: `someList.toSet()`, or use `Set(...)` literal.
  2. Change the declared type from `Set<T>` to `List<T>` if duplicates/order matter.
  3. Remember Pkl `Set` disallows duplicates; ensure the source data is set-like.
  4. Check that conversions of external data preserve Set semantics.

Example fix

// before
tags: Set<String> = List("a", "b")
// after
tags: Set<String> = List("a", "b").toSet()
Defensive patterns

Strategy: validation

Validate before calling

assert(s is Set, "Set<T> requires a Set; convert with .toSet()")
s: Set<String> = rawList.toSet()

Type guard

function toSetOrNull(v): Set* = if (v is Set) v else null

Prevention

When it happens

Trigger: Executing a `Set<T>` type check with a non-Set value, e.g. `s: Set<Int> = List(1,2,3)` or `s: Set<String> = "a,b"`.

Common situations: Declaring `Set<T>` but producing a List (very common since List literals are more idiomatic); converting JSON/YAML arrays whose semantics are lists; typo between Set and List in a typealias.

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

Appendix: source

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

      return consumer.accept(this);
    }

    @Specialization
    protected Object eval(VirtualFrame frame, VmSet value) {
      if (elementTypeNode.isNoopTypeCheck()) return value;
      for (var elem : value) {
        // no point doing a lazy check because set members have their hash code computed, which
        // necessarily deep-forces them.
        elementTypeNode.executeEagerly(frame, elem);
      }

      LoopNode.reportLoopCount(this, value.getLength());
      return value;
    }

    @Fallback
    protected Object fallback(Object value) {
      throw typeMismatch(value, BaseModule.getSetClass());
    }

    @Override
    protected boolean isParametric() {
      return true;
    }
  }

  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;
    }

View on GitHub (pinned to f3efcbfc9b)