google/gson · error · JsonSyntaxException
JSON document was not fully consumed.
Error message
JSON document was not fully consumed.
What it means
Thrown by assertFullConsumption (called from Gson.fromJson(Reader, TypeToken)) when, after successfully reading one JSON value, the reader still has more tokens (peek() != END_DOCUMENT). The Reader/TypeToken overload enforces single-value documents to catch trailing garbage; multiple top-level values or trailing whitespace-with-data are rejected. It is a JsonSyntaxException (a RuntimeException).
Source
Thrown at gson/src/main/java/com/google/gson/Gson.java:1222
*
* @return an object of type T from the JSON. Returns {@code null} if {@code json} is {@code null}
* or if {@code json} is empty.
* @throws JsonSyntaxException if json is not a valid representation for an object of type typeOfT
* @see #fromJson(Reader, TypeToken)
* @see #fromJson(JsonElement, Class)
* @since 2.10
*/
public <T> T fromJson(JsonElement json, TypeToken<T> typeOfT) throws JsonSyntaxException {
if (json == null) {
return null;
}
return fromJson(new JsonTreeReader(json), typeOfT);
}
private static void assertFullConsumption(Object obj, JsonReader reader) {
try {
if (obj != null && reader.peek() != JsonToken.END_DOCUMENT) {
throw new JsonSyntaxException("JSON document was not fully consumed.");
}
} catch (MalformedJsonException e) {
throw new JsonSyntaxException(e);
} catch (IOException e) {
throw new JsonIOException(e);
}
}
/**
* Proxy type adapter for cyclic type graphs.
*
* <p><b>Important:</b> Setting the delegate adapter is not thread-safe; instances of {@code
* FutureTypeAdapter} must only be published to other threads after the delegate has been set.
*
* @see Gson#threadLocalAdapterResults
*/
static class FutureTypeAdapter<T> extends SerializationDelegatingTypeAdapter<T> {
private TypeAdapter<T> delegate = null;View on GitHub (pinned to 8b8628c656)
Solutions
- Use the JsonReader-based overload gson.fromJson(JsonReader, TypeToken) which does NOT enforce full consumption and lets you loop over multiple top-level values.
- Strip trailing data or split the input into single JSON values before parsing.
- For NDJSON, read line-by-line and parse each line separately.
- Validate that the input contains exactly one top-level JSON value before calling the Reader overload.
Example fix
// before: two values in one Reader
String two = "{\"a\":1}{\"b\":2}";
Foo f = gson.fromJson(new StringReader(two), TypeToken.get(Foo.class)); // throws
// after: use JsonReader to consume multiple values
try (JsonReader r = new JsonReader(new StringReader(two))) {
while (r.peek() != JsonToken.END_DOCUMENT) {
Foo f = gson.fromJson(r, TypeToken.get(Foo.class));
}
} Defensive patterns
Strategy: validation
Validate before calling
// Validate single top-level value before the Reader overload
static boolean hasSingleTopLevel(String json) {
JsonReader r = new JsonReader(new StringReader(json));
try {
r.skipValue();
return r.peek() == JsonToken.END_DOCUMENT;
} catch (IOException e) { return false; }
} Type guard
static boolean isSingleValueDocument(Reader reader) {
JsonReader r = new JsonReader(reader);
try { r.skipValue(); return r.peek() == JsonToken.END_DOCUMENT; }
catch (IOException e) { return false; }
} Try / catch
try {
Foo f = gson.fromJson(reader, TypeToken.get(Foo.class));
} catch (JsonSyntaxException e) {
if (e.getMessage().contains("not fully consumed")) {
// switch to JsonReader-based loop for multi-value streams
} else throw e;
} Prevention
- Use the JsonReader overload (fromJson(JsonReader, TypeToken)) for streams with multiple values; it does not enforce full consumption.
- Split NDJSON into lines and parse each line separately.
- Validate single top-level value before using the Reader overload.
- Frame network/streamed JSON correctly so only one message reaches each parse call.
When it happens
Trigger: Feeding gson.fromJson(reader, TypeToken.get(Foo.class)) a stream containing two concatenated JSON objects {"a":1}{"b":2}; a value followed by trailing non-whitespace; an array where a single object was expected, or vice versa, leaving remainder; NDJSON/JSON Lines fed to a single-value parser.
Common situations: Concatenated responses from a server; NDJSON log files; buffered streams that include the next message; copy-paste of multiple JSON snippets into one input; incorrect framing of a network protocol.
Related errors
- Type adapter '{typeAdapter}' returned wrong type; requested
- cannot deserialize {baseType} because it does not define a f
- cannot deserialize {baseType} subtype named {label}; did you
- GSON ({GsonBuildConfig.VERSION}) cannot handle {type}
- GSON cannot serialize or deserialize {type}
AI-assisted analysis of google/gson@8b8628c656 (2026-08-04).
Data as JSON: /data/errors/1b059d4232aeda78.json.
Report an issue: GitHub.