apple/pkl · error · ParseException
digit
Error message
digit
What it means
A JSON number must start with at least one decimal digit after the optional minus sign, and leading zeros are not allowed (readDigit's first result is checked; if the first digit is '0', no further digits may follow it). readNumber throws expected("digit") when the character after '-' (or at the number's start) is not a digit — e.g. "-", "-x", or ".5" where a number was expected.
Source
Thrown at pkl-core/src/main/java/org/pkl/core/util/json/JsonParser.java:299
if (!isHexDigit()) {
throw expected("hexadecimal digit");
}
hexChars[i] = (char) current;
}
captureBuffer.append((char) Integer.parseInt(new String(hexChars), 16));
}
default -> throw expected("valid escape sequence");
}
read();
}
private void readNumber() throws IOException {
handler.startNumber();
startCapture();
readChar('-');
var firstDigit = current;
if (!readDigit()) {
throw expected("digit");
}
if (firstDigit != '0') {
//noinspection StatementWithEmptyBody
while (readDigit()) {}
}
readFraction();
readExponent();
handler.endNumber(endCapture());
}
@SuppressWarnings("UnusedReturnValue")
private boolean readFraction() throws IOException {
if (!readChar('.')) {
return false;
}
if (!readDigit()) {
throw expected("digit");
}View on GitHub (pinned to f3efcbfc9b)
Solutions
- Write the number with a leading digit: 0.5 instead of .5, and ensure '-' is followed by digits.
- Replace NaN/Infinity with null or strings — they are not valid JSON numbers.
- Check templating: if a variable failed to interpolate, the value position may be empty or a lone '-'.
- Catch ParseException and use its position to inspect the malformed number token.
Example fix
// before
String json = "{\"ratio\": .5}"; // no leading digit
// after
String json = "{\"ratio\": 0.5}"; Defensive patterns
Strategy: validation
Validate before calling
// Java: reject numbers lacking a leading digit before parsing
if (java.util.regex.Pattern.compile("(^|[\\[,\\s:])(-?)(\\.\\D|[-.]\\s*[,}\\]])").matcher(json).find()) {
throw new IllegalArgumentException("JSON numbers require at least one leading digit (0.5 not .5)");
} Try / catch
try {
parser.parse(json);
} catch (ParseException e) {
if (e.getMessage().contains("digit")) {
throw new IllegalArgumentException("Malformed JSON number at " + e.getLocation().line + ":" + e.getLocation().column + " — a digit was required", e);
}
throw e;
} Prevention
- Write 0.5, not .5; ensure '-' is always followed by digits.
- Replace NaN/Infinity with null — they are not valid JSON.
- Verify template variables actually interpolated into number positions.
- Format numbers with a JSON-aware serializer, not printf without fraction digits.
When it happens
Trigger: parse() on inputs like "{\"n\": -}" (dangling minus), "{\"n\": .5}" (leading dot), or a value position holding a non-number character, where readValue dispatched to readNumber because of '-' or a digit-like start.
Common situations: Hand-written JSON with .5 instead of 0.5, template variables left empty ("-" with the number interpolated away), NaN/Infinity pasted from JavaScript (not valid JSON numbers), truncated numeric output.
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/7c358782f252c242.
Report an issue: GitHub.