{"id":"a811dabef5ae53ba","repo":"google/gson","slug":"failed-parsing-json-source-reader-to-json","errorCode":null,"errorMessage":"Failed parsing JSON source: {reader} to Json","messagePattern":"Failed parsing JSON source: (.+?) to Json","errorType":"exception","errorClass":"JsonParseException","httpStatus":null,"severity":"critical","filePath":"gson/src/main/java/com/google/gson/JsonParser.java","lineNumber":146,"sourceCode":"   * Strictness#STRICT}, that strictness will be used for parsing. Otherwise the strictness will be\n   * temporarily changed to {@link Strictness#LENIENT} and will be restored once this method\n   * returns.\n   *\n   * @throws JsonParseException if there is an IOException or if the specified text is not valid\n   *     JSON\n   * @since 2.8.6\n   */\n  public static JsonElement parseReader(JsonReader reader)\n      throws JsonIOException, JsonSyntaxException {\n    Strictness strictness = reader.getStrictness();\n    if (strictness == Strictness.LEGACY_STRICT) {\n      // For backward compatibility change to LENIENT if reader has default strictness LEGACY_STRICT\n      reader.setStrictness(Strictness.LENIENT);\n    }\n    try {\n      return Streams.parse(reader);\n    } catch (StackOverflowError | OutOfMemoryError e) {\n      throw new JsonParseException(\"Failed parsing JSON source: \" + reader + \" to Json\", e);\n    } finally {\n      reader.setStrictness(strictness);\n    }\n  }\n\n  /**\n   * @deprecated Use {@link JsonParser#parseString}\n   */\n  @Deprecated\n  @InlineMe(replacement = \"JsonParser.parseString(json)\", imports = \"com.google.gson.JsonParser\")\n  public JsonElement parse(String json) throws JsonSyntaxException {\n    return parseString(json);\n  }\n\n  /**\n   * @deprecated Use {@link JsonParser#parseReader(Reader)}\n   */\n  @Deprecated","sourceCodeStart":128,"sourceCodeEnd":164,"githubUrl":"https://github.com/google/gson/blob/8b8628c65699bc4421696183c62ae0c1b9b281dc/gson/src/main/java/com/google/gson/JsonParser.java#L128-L164","documentation":"Thrown by JsonParser.parseReader(JsonReader) when Streams.parse(reader) raises StackOverflowError or OutOfMemoryError, wrapping the VM error in a JsonParseException. It almost always indicates pathologically deep or huge JSON that exceeds default stack/heap limits rather than a syntax problem.","triggerScenarios":"Parsing deeply nested JSON (thousands of nested objects/arrays) triggering StackOverflowError; parsing a multi-GB single document exhausting heap; recursive data structures serialized verbatim.","commonSituations":"Untrusted input from web crawlers; misbehaving upstream producing unbounded nesting; default -Xss/-Xmx too small for the workload; gzip bombs expanded by a proxy.","solutions":["Raise -Xss (thread stack) and/or -Xmx if the input is legitimately large.","Bound nesting depth by streaming with JsonReader and rejecting documents beyond a depth threshold before full parse.","Cap request body size at the network boundary to prevent heap exhaustion.","Reject or pre-validate untrusted JSON with a depth/size limit before handing it to Gson."],"exampleFix":"// before\nJsonElement e = JsonParser.parseReader(reader);\n\n// after (depth-bounded streaming)\ntry (JsonReader r = new JsonReader(reader)) {\n  // read tokens, throw custom exception if depth > MAX_DEPTH\n} catch (StackOverflowError s) {\n  throw new IllegalArgumentException(\"JSON nesting too deep\", s);\n}","handlingStrategy":"validation","validationCode":"// reject documents beyond size/depth limits before parsing\nif (json.length() > MAX_BYTES) throw new IllegalArgumentException(\"too large\");\n","typeGuard":"boolean withinDepthLimit(JsonElement e, int max) {\n  if (max < 0) return false;\n  if (e.isJsonObject())\n    return e.getAsJsonObject().entrySet().stream()\n      .allMatch(x -> withinDepthLimit(x.getValue(), max - 1));\n  if (e.isJsonArray())\n    return e.getAsJsonArray().asList().stream()\n      .allMatch(x -> withinDepthLimit(x, max - 1));\n  return true;\n}\n","tryCatchPattern":"try {\n  return JsonParser.parseReader(reader);\n} catch (JsonParseException ex) {\n  if (ex.getCause() instanceof StackOverflowError\n      || ex.getCause() instanceof OutOfMemoryError) {\n    throw new IllegalArgumentException(\"input too large or deeply nested\", ex);\n  }\n  throw ex;\n}\n","preventionTips":["Cap request body size at the network layer.","Bound JSON nesting depth in a streaming pre-pass.","Size -Xss/-Xmx to the largest legitimate document."],"tags":["parsing","resource-exhaustion","stack-overflow","oom"],"analyzedSha":"8b8628c65699bc4421696183c62ae0c1b9b281dc","analyzedAt":"2026-08-04T19:12:22.202Z","schemaVersion":2}