apple/pkl · error · VmTypeMismatchException

type mismatch: value is not one of the expected string liter

Error message

type mismatch: value is not one of the expected string literals

What it means

Pkl multiple string-literal type check failure. The declared type is a union of string literals (e.g. `"a" | "b" | "c"`, amenable typecheck via `contains`), and the runtime value was not any of the accepted literals. Unlike error 671 (single literal), this node validates against a whole set of string literals.

Source

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

    @Override
    public VmTyped getMirror() {
      return MirrorFactories.unionOfStringLiteralsTypeFactory.create(this);
    }

    public VmList getElementTypeMirrors() {
      var builder = VmList.EMPTY.builder();
      for (var literal : stringLiterals) {
        builder.add(MirrorFactories.stringLiteralTypeFactory2.create(literal));
      }
      return builder.build();
    }

    @Override
    protected Object executeLazily(VirtualFrame frame, Object value) {
      if (contains(value)) return value;

      throw typeMismatch(value, stringLiterals);
    }

    @TruffleBoundary
    private boolean contains(Object value) {
      //noinspection SuspiciousMethodCalls
      return stringLiterals.contains(value);
    }

    @Override
    protected PType doExport() {
      return new PType.Union(
          stringLiterals.stream().map(StringLiteral::new).collect(Collectors.toList()));
    }

    @Override
    @TruffleBoundary
    public boolean doIsEquivalentTo(TypeNode other) {
      if (!(other instanceof UnionOfStringLiteralsTypeNode unionOfStringLiteralsTypeNode)) {

View on GitHub (pinned to f3efcbfc9b)

Solutions

  1. Use one of the exact literals listed in the declared union type.
  2. Extend the union type to include the new valid literal (`"prod" | "staging" | "dev"`).
  3. Normalize input casing/whitespace before assignment.
  4. Replace the union with a type alias or enum-like module so valid values are documented in one place.

Example fix

// before
env: "dev" | "prod" = "production"
// after
env: "dev" | "prod" = "prod"   // or widen type to include "production"
Defensive patterns

Strategy: validation

Validate before calling

// Pkl
allowed: List<String> = List("dev", "staging", "prod")
if (!allowed.contains(value)) throw("\(value) not in \(allowed)")

Type guard

function isAllowedEnv(value: Any): Boolean = value is String && List("dev","staging","prod").contains(value)

Try / catch

// Validate membership in the literal union before assignment; embedders: catch PklException with 'not one of the expected string literals'.

Prevention

When it happens

Trigger: Assigning a string not present in the declared literal union (typo, casing, unsupported enum member); assigning a non-string value to a string-literal-union property.

Common situations: Enum-like config fields (log levels, environments, regions) receiving an unsupported value; adding a new environment name without extending the union type; case differences from environment variables.

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