JSON Errors / Java

com.google.gson.JsonSyntaxException: MalformedJsonException

How to Fix: com.google.gson.JsonSyntaxException: MalformedJsonException

Gson could not parse the input as strict JSON. Despite the famous suggestion in the message - "Use JsonReader.setLenient(true) to accept malformed JSON" - lenient mode is almost never the right fix: the input is genuinely not valid JSON, and you should find out why.

The exception message includes "at line X column Y path $.field", which tells you exactly where parsing derailed - the path notation ($.items[2].name) is the JSON path to the failing token.

{"find": "error"}paste your JSON below

Common causes

1. The server returned HTML or plain text

An error page or redirect instead of JSON - the Java equivalent of the JavaScript "Unexpected token <" error. Common with expired tokens and wrong base URLs in Retrofit clients.

2. Unquoted or single-quoted values

Hand-built JSON with missing quotes fails in strict mode: {name: John} needs {"name": "John"}.

Invalid
{name: John, age: 30}
Valid
{"name": "John", "age": 30}

3. Trailing data after the document

"MalformedJsonException: Expected EOF" means content followed the first complete JSON value - concatenated documents or log noise appended to the payload.

4. Truncated response

"End of input at line X" means the JSON stops mid-document - a dropped connection, a timeout that returned a partial body, or a stream read too early.

How to fix it

Log the raw body before parsing (OkHttp/Retrofit)
// Add an interceptor to see what actually arrived:
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder()
    .addInterceptor(logging)
    .build();
Check HTTP status before deserializing
Response<User> response = call.execute();
if (!response.isSuccessful()) {
    String error = response.errorBody() != null
        ? response.errorBody().string() : "unknown";
    throw new IOException("HTTP " + response.code() + ": " + error);
}
User user = response.body();

Frequently asked questions

Should I just use setLenient(true) like the message says?

Almost never. Lenient mode accepts unquoted values, comments, and multiple documents - it papers over the symptom while your code processes data that is wrong in some other way (an error page parsed as an object full of nulls). Find the real source; use lenient mode only for legacy feeds you cannot fix.

What does "Expected BEGIN_OBJECT but was STRING" mean?

A related Gson error: the JSON is valid, but its shape does not match your class - the payload has a string where your model declares an object, often because the API wraps responses ({"data": {...}}) or returns an error object on failure. Adjust the model or unwrap first.

How do I read the "path $.items[2].name" part?

$ is the document root, so $.items[2].name means: root object → "items" array → third element → "name" field. Look at that exact location in the raw response to see what Gson choked on.

Last updated:

Related JSON errors

You might also need

Free and in-browser, like everything on JSON Console. Browse all tools →