apple/pkl · error · ParserError

unexpectedToken2

unexpectedToken2

Error message

Unexpected token `{0}`. Expected `{1}` or `{2}`.

What it means

`parseBodyList` expects a Pkl object body member that is either a `{...}` object body or an `= ...` property assignment. When the first token of a body list member is not `{`, the parser throws `unexpectedToken2` listing both accepted tokens. This enforces that class/object members start with a body or assignment.

Solutions

  1. Use `=` for property assignment: `x = 1`
  2. Use `{ ... }` for object bodies: `x { y = 1 }`
  3. Remove the invalid token if it is leftover from another syntax

Example fix

// before
foo: 1
// after
foo = 1
Defensive patterns

Strategy: validation

Validate before calling

function bodyMembersAreValid(src) {
  return !/^\s*\w+\s*:/m.test(src);
}
// Pkl object bodies do not use JSON-style `name: value`

Try / catch

try { parse(src) } catch (e) {
  if (String(e.message).includes('Expected \"{\" or \"=\"')) {
    throw new Error('Pkl members must start with { or = : ' + e.message);
  }
  throw e;
}

Prevention

When it happens

Trigger: Parsing an `amends`/class member list where a member starts with something other than `{` or `=`, e.g. a bare identifier or `,` where a body should be.

Common situations: Using JSON-style `name: value` inside a Pkl object body where `name { ... }` or `name = value` is required; copy-pasted YAML/JSON syntax into Pkl.

Understand the failure class

Related errors


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

Appendix: source

Thrown at pkl-parser/src/main/java/org/pkl/parser/ParserImpl.java:1526

    return modifiers;
  }

  private ParameterList parseParameterList() {
    var start = expect(Token.LPAREN, "unexpectedToken", "(").span;
    Span end;
    List<Parameter> args = new ArrayList<>();
    if (lookahead == Token.RPAREN) {
      end = next().span;
    } else {
      args = parseListOfParameter(Token.COMMA, Token.RPAREN);
      end = expect(Token.RPAREN, "unexpectedToken2", ",", ")").span;
    }
    return new ParameterList(args, start.endWith(end));
  }

  private List<ObjectBody> parseBodyList() {
    if (lookahead != Token.LBRACE) {
      throw parserError("unexpectedToken2", _lookahead.text(lexer), "{", "=");
    }
    var bodies = new ArrayList<ObjectBody>();
    do {
      bodies.add(parseObjectBody());
    } while (lookahead == Token.LBRACE);
    return bodies;
  }

  private TypeParameterList parseTypeParameterList() {
    var start = expect(Token.LT, "unexpectedToken", "<").span;
    var pars = parseListOf(Token.COMMA, Token.GT, this::parseTypeParameter);
    var end = expect(Token.GT, "unexpectedToken2", ",", ">").span;
    return new TypeParameterList(pars, start.endWith(end));
  }

  private TypeArgumentList parseTypeArgumentList() {
    var start = expect(Token.LT, "unexpectedToken", "<").span;
    var pars = parseListOf(Token.COMMA, Token.GT, this::parseType);

View on GitHub (pinned to f3efcbfc9b)