apple/pkl · error · GenericParserError

notAUnion

notAUnion

Error message

Only type unions can have a default marker (*).

What it means

Pkl's `*` token marks the default member of a type union (e.g. `*"a"|*"b"`). When the parser finishes the first type atom and the next token is not `|` (no union follows) but a default marker was consumed, it throws notAUnion — a default marker is meaningless outside a union.

Solutions

  1. Remove the `*` marker if the type is not a union.
  2. Add the missing union member(s), e.g. change `*String` to `*"a"|"b"` or `"a"|*"b"`.
  3. Check for a swallowed `|` character during editing or copy-paste.

Example fix

// before
name: *"apple"

// after
name: *"apple"|"orange"
Defensive patterns

Strategy: validation

Validate before calling

// A `*` in a type position must be followed by more union members
function defaultMarkerInUnion(typeExpr) {
  if (!typeExpr.includes('*')) return true;
  return typeExpr.includes('|');
}

Prevention

When it happens

Trigger: Writing a type like `*String` or `*"x"` without a `|` union — e.g. a type annotation `x: *String` or an ambiguous `var x: *Foo = ...`.

Common situations: Typos where the `|` separating union members was deleted; misunderstanding `*` as a wildcard or pointer; copy-pasting a union default from an example and trimming the union to one member.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of apple/pkl@f3efcbfc9b (2026-09-08). Data as JSON: /api/errors/0ca2e2686445eabc. Report an issue: GitHub.

Appendix: source

Thrown at pkl-parser/src/main/java/org/pkl/parser/GenericParserImpl.java:1135

  private Node parseType(@Nullable String expectation) {
    var children = new ArrayList<Node>();
    var hasDefault = false;
    FullSpan start = null;
    if (lookahead == Token.STAR) {
      var tk = next();
      start = tk.span;
      children.add(makeTerminal(tk));
      ff(children);
      hasDefault = true;
    }
    var first = parseTypeAtom(expectation);
    children.add(first);

    if (lookahead() != Token.UNION) {
      if (hasDefault) {
        //noinspection ConstantValue (NullAway needs this assertion, IntelliJ doesn't)
        assert start != null;
        throw parserError(ErrorMessages.create("notAUnion"), start.endWith(first.span));
      }
      return first;
    }

    while (lookahead() == Token.UNION) {
      ff(children);
      children.add(makeTerminal(next()));
      ff(children);
      if (lookahead == Token.STAR) {
        if (hasDefault) {
          throw parserError("multipleUnionDefaults");
        }
        children.add(makeTerminal(next()));
        ff(children);
        hasDefault = true;
      }
      var type = parseTypeAtom(expectation);
      children.add(type);

View on GitHub (pinned to f3efcbfc9b)