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
- Spell literals in lowercase exactly: true, false, null — JSON is case-sensitive.
- Check the ParseException position to see which literal was misspelled or truncated and fix the source.
- If input may be truncated, verify completeness (e.g. content-length check or a final validation pass) before parsing.
- 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
- Use exactly true, false, null (lowercase) in JSON.
- Convert booleans with the language's JSON serializer, not manual string building.
- Verify input completeness to avoid truncated literals.
- Grep generated files for True/False/None before parsing.
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.