apple/pkl · error · ParserError

unexpectedEndOfFile

unexpectedEndOfFile

Error message

Unexpected end of file.

What it means

The Pkl parser reached the end of the input file while it still expected more tokens — for example in the middle of an expression, argument list, or identifier reference. The parser throws this instead of a generic unexpected-token error when the lookahead token is EOF, because the real problem is missing input, not wrong input. It points at the position one past the last parsed token.

Source

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

            var tk = next();
            yield new FloatLiteralExpr(tk.text(lexer), tk.span);
          }
          case STRING_START -> parseSingleLineStringLiteralExpr();
          case STRING_MULTI_START -> parseMultiLineStringLiteralExpr();
          case IDENTIFIER -> {
            var identifier = parseIdentifier();
            if (lookahead == Token.LPAREN
                && !precededBySemicolon
                && _lookahead.newLinesBetween == 0) {
              var args = parseArgumentList();
              yield new UnqualifiedAccessExpr(
                  identifier, args, identifier.span().endWith(args.span()));
            } else {
              yield new UnqualifiedAccessExpr(identifier, null, identifier.span());
            }
          }
          case EOF ->
              throw new ParserError(
                  ErrorMessages.create("unexpectedEndOfFile"), prev.span.stopSpan().move(1));
          default -> {
            var text = _lookahead.text(lexer);
            if (expectation != null) {
              throw parserError("unexpectedToken", text, expectation);
            }
            throw parserError("unexpectedTokenForExpression", text);
          }
        };
    return parseExprRest(expr);
  }

  @SuppressWarnings("DuplicatedCode")
  private Expr parseExprRest(Expr expr) {
    // non-null
    if (lookahead == Token.NON_NULL) {
      var end = next().span;
      var res = new NonNullExpr(expr, expr.span().endWith(end));

View on GitHub (pinned to f3efcbfc9b)

Solutions

  1. Scan the source at the reported stop position and close the nearest unclosed bracket, paren, or quote above it
  2. Check for a trailing incomplete expression (e.g. a dangling operator or arrow) and complete or remove it
  3. Verify the file was fully written/transferred — compare byte size or re-save the source
  4. If generating Pkl programmatically, assert balanced delimiters before invoking the parser

Example fix

// before (truncated)
x = foo(
// after
x = foo(1, 2)
Defensive patterns

Strategy: try-catch

Validate before calling

function checkBalancedDelimiters(src) {
  const pairs = {'{':'}','(':')','[':']'};
  const stack = [];
  let inStr = false, esc = false;
  for (const ch of src) {
    if (esc) { esc = false; continue; }
    if (ch === '\\') { esc = true; continue; }
    if (ch === '"') { inStr = !inStr; continue; }
    if (inStr) continue;
    if (pairs[ch]) stack.push(pairs[ch]);
    else if (Object.values(pairs).includes(ch) && stack.pop() !== ch) return false;
  }
  return !inStr && stack.length === 0;
}
// run before invoking the parser; abort if false

Type guard

null

Try / catch

try {
  const result = pkl.evaluateSource(src);
} catch (e) {
  if (e instanceof ParserError && e.errorId === 'unexpectedEndOfFile') {
    // append missing closers or report position e.span.start
  } else { throw e; }
}

Prevention

When it happens

Trigger: Calling the parser (e.g. via pkl.evaluateSource / ParserImpl.parse) on source that ends prematurely: an unclosed `{`, `(`, `[`, or string literal, a trailing operator like `1 +`, a dangling `->` in a type, or a truncated file passed in.

Common situations: Files cut off by an incomplete download or failed save; copy-pasting a snippet and dropping the closing brace; generating Pkl code programmatically and emitting an unbalanced delimiter; heredoc/template tooling swallowing the final lines.

Related errors


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