apple/pkl · error · GenericParserError

unexpectedTokenForType

unexpectedTokenForType

Error message

Unexpected token `{0}`. Expected a type.

What it means

The expectation-less variant thrown by parseType's default branch: a token that cannot start a type was found, and no expectation hint is available. The message includes the offending token text and simply states a type was expected.

Solutions

  1. Replace the token with a valid type (e.g. String, Int, MyClass, `module`, or a union).
  2. Check for typos in the type name or stray characters in the annotation.
  3. Verify the type is declared/imported if a custom type was intended.
  4. Wrap constant string types in quotes if a literal-typed value was meant, e.g. `"prod"`.

Example fix

// before
port: 8

// after
port: Int
Defensive patterns

Strategy: validation

Validate before calling

// Type annotation slots must start with a type-starting token
function typeAnnotationWellFormed(src) {
  return !/:\s*(?![A-Za-z_\"(])[\s\S]/.test(src);
}

Prevention

When it happens

Trigger: A type annotation, extends clause, type alias, or type constraint position contains a non-type token — e.g. `x: 5`, `foo: ->`, or an operator/keyword in type position where parseType was called without an expectation.

Common situations: Typos in type names; using value syntax instead of type syntax in annotations; generated .pkl emitting placeholders like `???` in type slots; editors auto-completing wrong tokens.

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

Appendix: source

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

            }
          }
          case IDENTIFIER -> {
            var children = new ArrayList<Node>();
            children.add(parseQualifiedIdentifier());
            if (lookahead() == Token.LT) {
              ff(children);
              children.add(parseTypeArgumentList());
            }
            yield new Node(NodeType.DECLARED_TYPE, children);
          }
          case STRING_START ->
              new Node(NodeType.STRING_CONSTANT_TYPE, List.of(parseStringConstant()));
          default -> {
            var text = _lookahead.text(lexer);
            if (expectation != null) {
              throw parserError("unexpectedTokenForType2", text, expectation);
            }
            throw parserError("unexpectedTokenForType", text);
          }
        };

    if (typ.type == NodeType.FUNCTION_TYPE) return typ;
    return parseTypeEnd(typ);
  }

  private Node parseTypeEnd(Node type) {
    var children = new ArrayList<Node>();
    children.add(type);
    // nullable types
    if (lookahead() == Token.QUESTION) {
      ff(children);
      children.add(makeTerminal(next()));
      var res = new Node(NodeType.NULLABLE_TYPE, children);
      return parseTypeEnd(res);
    }
    // constrained types: have to start in the same line as the type

View on GitHub (pinned to f3efcbfc9b)