google/gson · error · MalformedJsonException
See
Error message
${message}${locationString()}
See ${TroubleshootingGuide.createUrl("malformed-json")} What it means
Thrown by JsonReader.syntaxError() as a com.google.gson.stream.MalformedJsonException (an IOException subclass). It is the single funnel for ~21 distinct syntax violations in the reader (unterminated array/object/string/escape/comment, 'Expected name', 'Expected :', 'Expected value', 'Unexpected value', 'JSON forbids NaN and infinities', 'Malformed Unicode escape', 'Invalid escape sequence', 'Cannot escape a newline character in strict mode', 'Invalid escaped character in strict mode', 'String contains non-ASCII characters'). The message is composed as the specific reason plus a location string ('at line L column C path $...') and a troubleshooting URL. The exception is raised at JsonReader.java:1840-1841.
Solutions
- Inspect the reported line/column/path in the message to locate the offending byte, then fix the source data at that position.
- Validate the input with a strict JSON parser or jsonlint before feeding it to Gson to get a clearer error.
- If the input uses lenient syntax (comments, single quotes, unquoted keys, multiple top-level values), set reader.setStrictness(Strictness.LENIENT) before reading.
- For truncated streams, ensure the producer writes complete JSON and the transport does not cut off mid-document; read fully into memory before parsing if partial reads are possible.
- If you cannot change the data, switch to a tolerant reader or pre-process (strip comments, normalize quotes) before parsing.
Example fix
// before
JsonReader r = new JsonReader(new StringReader("{'k': 1,}")); // single quotes + trailing comma
r.beginObject(); // throws MalformedJsonException: ... See ...#malformed-json
// after (accept lenient input)
JsonReader r = new JsonReader(new StringReader("{'k': 1,}"));
r.setStrictness(Strictness.LENIENT);
r.beginObject(); Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-validate the payload with a strict parser before handing to Gson.
// Using javax.json (Jakarta JSON-P) as an independent validator:
import javax.json.Json;
import javax.json.JsonReader;
// returns normally if valid, throws on malformed input
void validateStrict(String payload) {
try (JsonReader r = Json.createReader(new StringReader(payload))) {
r.read(); // throws JsonParsingException on any syntax error
}
} Type guard
null
Try / catch
try {
T obj = gson.fromJson(payload, type);
} catch (com.google.gson.JsonSyntaxException e) {
// Gson wraps MalformedJsonException in JsonSyntaxException when using Gson.fromJson(...)
Throwable cause = e.getCause();
if (cause instanceof com.google.gson.stream.MalformedJsonException) {
// message already contains line/column/path and a troubleshooting URL
log.warn("Malformed JSON rejected: {}", cause.getMessage());
}
throw e;
}
// When using JsonReader directly:
try (JsonReader r = new JsonReader(reader)) {
r.setStrictness(Strictness.STRICT);
// ... consume ...
} catch (com.google.gson.stream.MalformedJsonException e) {
// e.getMessage() ends with 'See https://github.com/google/gson/blob/main/Troubleshooting.md#malformed-json'
throw new InvalidPayloadException("Bad JSON input: " + e.getMessage(), e);
} Prevention
- Set reader strictness explicitly at construction so behavior does not depend on Gson defaults that change between versions.
- Validate external/untrusted JSON with a strict parser or schema before deserialization.
- Capture the line/column/path from the exception message to pinpoint the data error.
- When streaming from network, fully buffer and boundary-check before parsing to avoid truncated-input failures.
- If producers emit lenient dialects (comments, single quotes), agree on Strictness.LENIENT at both ends and document it.
When it happens
Trigger: Calling any JsonReader consuming method (peek, nextString, nextBoolean, nextDouble, nextLong, nextName, skipValue, or Gson.fromJson via the reader) on input that violates RFC 8259; unterminated literals; stray characters between tokens; single quotes or unquoted names when strictness is STRICT/LEGACY_STRICT; a missing colon after a name; a trailing comma in strict mode; an embedded NaN/Infinity literal; a \uXXXX sequence with non-hex digits; a raw newline or apostrophe escaped only in STRICT mode.
Common situations: Reading JSON produced by a lenient writer or another language's serializer that emits comments, single-quoted strings, unquoted keys, or trailing commas; truncated network responses or partial file reads (unterminated structures); BOM or non-ASCII bytes in a stream decoded as the wrong charset; version mismatch where input previously tolerated under old lenient defaults now fails because Gson tightened defaults to LEGACY_STRICT; copy-pasting JSON with smart quotes or trailing punctuation.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- JSON must have only one top-level value.
- Did not consume the entire document.
- End of input
- Expected a long but was
- Failed parsing JSON source
AI-assisted analysis of google/gson@310ac341f2 (2026-08-10).
Data as JSON: /api/errors/750de0e83fd58ce6.
Report an issue: GitHub.
Appendix: source
Thrown at gson/src/main/java/com/google/gson/stream/JsonReader.java:1840
if (strictness == Strictness.STRICT) {
throw syntaxError("Invalid escaped character \"'\" in strict mode");
}
case '"':
case '\\':
case '/':
return escaped;
default:
// throw error when none of the above cases are matched
throw syntaxError("Invalid escape sequence");
}
}
/**
* Throws a new {@link MalformedJsonException} with the given message and information about the
* current location.
*/
private MalformedJsonException syntaxError(String message) throws MalformedJsonException {
throw new MalformedJsonException(
message + locationString() + "\nSee " + TroubleshootingGuide.createUrl("malformed-json"));
}
private IllegalStateException unexpectedTokenError(String expected) throws IOException {
JsonToken peeked = peek();
String troubleshootingId =
peeked == JsonToken.NULL ? "adapter-not-null-safe" : "unexpected-json-structure";
return new IllegalStateException(
"Expected "
+ expected
+ " but was "
+ peek()
+ locationString()
+ "\nSee "
+ TroubleshootingGuide.createUrl(troubleshootingId));
}
/** Consumes the non-execute prefix if it exists. */View on GitHub (pinned to 310ac341f2)