google/gson · critical · JsonParseException
Failed parsing JSON source
Error message
Failed parsing JSON source: ${reader} to Json What it means
Thrown as JsonParseException by JsonParser.parseReader(JsonReader) (JsonParser.java:146) when Streams.parse(reader) raises StackOverflowError or OutOfMemoryError; the VM error is caught and wrapped. It signals the input is pathologically deep (stack overflow) or too large for available heap (out of memory). This is a resource/DoS condition, not a JSON syntax error.
Solutions
- Stream with JsonReader (event-based, constant-ish memory) instead of building a full JsonElement tree
- Increase JVM stack (-Xss) and/or heap (-Xmx) if the payload is legitimately large
- Reject oversized payloads and/or cap nesting depth before parsing (size + depth pre-check)
- For untrusted input, pair streaming with an explicit depth counter and abort past a threshold
Example fix
// before: builds whole tree, can SOF/OOM
JsonElement e = JsonParser.parseString(massiveOrDeepJson);
// after: streaming parse with a depth guard
try (JsonReader r = new JsonReader(new StringReader(massiveOrDeepJson))) {
int depth = 0, maxDepth = 512;
while (r.peek() != JsonToken.END_DOCUMENT) {
JsonToken t = r.peek();
if (t == JsonToken.BEGIN_ARRAY || t == JsonToken.BEGIN_OBJECT) {
if (++depth > maxDepth) throw new IllegalStateException("nesting too deep");
// begin as needed
} else if (t == JsonToken.END_ARRAY || t == JsonToken.END_OBJECT) {
depth--;
}
r.skipValue(); // or handle the token
}
} Defensive patterns
Strategy: validation
Validate before calling
// reject oversized / over-deep input before parsing
if (raw.length() > MAX_BYTES) throw new IllegalArgumentException("payload too large");
// enforce depth with a streaming reader (see exampleFix) instead of building a full tree Try / catch
try {
JsonElement e = JsonParser.parseString(raw);
} catch (JsonParseException ex) {
if (ex.getMessage().startsWith("Failed parsing JSON source")) {
// underlying cause was StackOverflowError or OutOfMemoryError
}
} Prevention
- Stream with JsonReader for large or untrusted input rather than building a full tree
- Cap input size and nesting depth at the trust boundary
- Size the JVM (-Xss/-Xmx) to the workload
- Treat deep nesting as a potential DoS vector
When it happens
Trigger: Deeply nested arrays/objects causing StackOverflowError (e.g. tens of thousands of nested '['), or a payload so large that building the full JsonElement tree exhausts the heap (OutOfMemoryError).
Common situations: Untrusted/malicious input (a JSON nesting bomb such as '[[[[...]]]]'); very large log or metadata files parsed in one shot; recursive data structures serialized to deeply nested JSON; JVM launched with insufficient -Xss/-Xmx for the workload.
Related errors
- Did not consume the entire document.
- See
- Number has unsupported scale
- Number string too large
- End of input
AI-assisted analysis of google/gson@310ac341f2 (2026-08-10).
Data as JSON: /api/errors/4ff7c6d30c1b8f2a.
Report an issue: GitHub.
Appendix: source
Thrown at gson/src/main/java/com/google/gson/JsonParser.java:146
* Strictness#STRICT}, that strictness will be used for parsing. Otherwise the strictness will be
* temporarily changed to {@link Strictness#LENIENT} and will be restored once this method
* returns.
*
* @throws JsonParseException if there is an IOException or if the specified text is not valid
* JSON
* @since 2.8.6
*/
public static JsonElement parseReader(JsonReader reader)
throws JsonIOException, JsonSyntaxException {
Strictness strictness = reader.getStrictness();
if (strictness == Strictness.LEGACY_STRICT) {
// For backward compatibility change to LENIENT if reader has default strictness LEGACY_STRICT
reader.setStrictness(Strictness.LENIENT);
}
try {
return Streams.parse(reader);
} catch (StackOverflowError | OutOfMemoryError e) {
throw new JsonParseException("Failed parsing JSON source: " + reader + " to Json", e);
} finally {
reader.setStrictness(strictness);
}
}
/**
* @deprecated Use {@link JsonParser#parseString}
*/
@Deprecated
@InlineMe(replacement = "JsonParser.parseString(json)", imports = "com.google.gson.JsonParser")
public JsonElement parse(String json) throws JsonSyntaxException {
return parseString(json);
}
/**
* @deprecated Use {@link JsonParser#parseReader(Reader)}
*/
@DeprecatedView on GitHub (pinned to 310ac341f2)