apple/pkl · error · ParseException

'" + ch + "'

Error message

'" + ch + "'

What it means

The literals true, false, and null must be spelled exactly. readTrue, readFalse, and readNull each call readRequiredChar for their remaining letters; when the next character does not match, readRequiredChar throws expected("'<ch>'"). The message interpolates the expected character, e.g. expected 'r' for a malformed "true".

Source

Thrown at pkl-core/src/main/java/org/pkl/core/util/json/JsonParser.java:240

    readRequiredChar('r');
    readRequiredChar('u');
    readRequiredChar('e');
    handler.endBoolean(true);
  }

  private void readFalse() throws IOException {
    handler.startBoolean();
    read();
    readRequiredChar('a');
    readRequiredChar('l');
    readRequiredChar('s');
    readRequiredChar('e');
    handler.endBoolean(false);
  }

  private void readRequiredChar(char ch) throws IOException {
    if (!readChar(ch)) {
      throw expected("'" + ch + "'");
    }
  }

  private void readString() throws IOException {
    handler.startString();
    handler.endString(readStringInternal());
  }

  private String readStringInternal() throws IOException {
    read();
    startCapture();
    while (current != '"') {
      if (current == '\\') {
        pauseCapture();
        readEscape();
        startCapture();
      } else if (current < 0x20) {
        throw expected("valid string character");

View on GitHub (pinned to f3efcbfc9b)

Solutions

  1. Spell literals in lowercase exactly: true, false, null — JSON is case-sensitive.
  2. Check the ParseException position to see which literal was misspelled or truncated and fix the source.
  3. If input may be truncated, verify completeness (e.g. content-length check or a final validation pass) before parsing.
  4. Catch ParseException around parse() and surface a friendly 'invalid literal' message.

Example fix

// before
String json = "{\"ok\": True}"; // Python-style capitalization
// after
String json = "{\"ok\": true}";
Defensive patterns

Strategy: validation

Validate before calling

// Java: check literals are exactly lowercase before parsing
if (java.util.regex.Pattern.compile("\\b(True|False|TRUE|FALSE|NULL|None)\\b").matcher(json).find()) {
  throw new IllegalArgumentException("JSON literals must be exactly: true, false, null");
}

Try / catch

try {
  parser.parse(json);
} catch (ParseException e) {
  if (e.getMessage().matches("expected '[a-z]'")) {
    throw new IllegalArgumentException("Misspelled true/false/null literal at " + e.getLocation().line + ":" + e.getLocation().column, e);
  }
  throw e;
}

Prevention

When it happens

Trigger: parse() on inputs like "tru", "True", "FALSE", "nul", or a literal truncated mid-word (e.g. stream cut off after "fal"), where readRequiredChar finds a mismatching character or EOF.

Common situations: Case-typed booleans (True/False from Python style), truncated network responses, template variables left empty mid-literal ("tru${x}"), search-and-replace accidents in config files.

Understand the failure class

Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.

Related errors


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