{"id":"d91c9cf9d8a20222","repo":"google/gson","slug":"json-forbids-nan-and-infinities-result","errorCode":null,"errorMessage":"JSON forbids NaN and infinities: {result}","messagePattern":"JSON forbids NaN and infinities: (.+?)","errorType":"exception","errorClass":"MalformedJsonException","httpStatus":null,"severity":"error","filePath":"gson/src/main/java/com/google/gson/internal/bind/JsonTreeReader.java","lineNumber":254,"sourceCode":"    }\n  }\n\n  @Override\n  public double nextDouble() throws IOException {\n    JsonToken token = peek();\n    if (token != JsonToken.NUMBER && token != JsonToken.STRING) {\n      throw new IllegalStateException(\n          \"Expected \" + JsonToken.NUMBER + \" but was \" + token + locationString());\n    }\n    JsonPrimitive primitive = (JsonPrimitive) peekStack();\n    double result;\n    try {\n      result = primitive.getAsDouble();\n    } catch (NumberFormatException e) {\n      throw numberFormatException(\"Expected a double but was \" + primitive.getAsString(), e);\n    }\n    if (!isLenient() && (Double.isNaN(result) || Double.isInfinite(result))) {\n      throw new MalformedJsonException(\"JSON forbids NaN and infinities: \" + result);\n    }\n    popStack();\n    if (stackSize > 0) {\n      pathIndices[stackSize - 1]++;\n    }\n    return result;\n  }\n\n  @Override\n  public long nextLong() throws IOException {\n    JsonToken token = peek();\n    if (token != JsonToken.NUMBER && token != JsonToken.STRING) {\n      throw new IllegalStateException(\n          \"Expected \" + JsonToken.NUMBER + \" but was \" + token + locationString());\n    }\n    JsonPrimitive primitive = (JsonPrimitive) peekStack();\n    if (token == JsonToken.STRING) {\n      validateAscii(primitive.getAsString());","sourceCodeStart":236,"sourceCodeEnd":272,"githubUrl":"https://github.com/google/gson/blob/8b8628c65699bc4421696183c62ae0c1b9b281dc/gson/src/main/java/com/google/gson/internal/bind/JsonTreeReader.java#L236-L272","documentation":"JsonTreeReader.nextDouble throws MalformedJsonException('JSON forbids NaN and infinities: ' + result) when the parsed double value is NaN or +/-Infinity AND the reader is not lenient. Strict JSON (RFC 8259) does not permit NaN or Infinity literals; only lenient mode tolerates them. The {result} is the offending numeric value.","triggerScenarios":"Reading a JsonPrimitive holding Double.NaN, POSITIVE_INFINITY, or NEGATIVE_INFINITY through a non-lenient JsonTreeReader.nextDouble(). Common when the source tree was built from a Java object that had NaN/Infinity doubles and then re-serialized strictly.","commonSituations":"Math/finance code producing NaN or Infinity; sensor data with NaN sentinels; deserializing a tree that a lenient writer produced back through a strict reader; default Gson is non-lenient.","solutions":["Enable lenient mode: construct the JsonReader and call setLenient(true) before reading (note: Gson.fromJson defaults are strict).","Sanitize the source: replace NaN/Infinity with null or a sentinel value before building the tree.","Register a custom TypeAdapter for double/Double that converts NaN/Infinity to null or a defined sentinel on write and accepts it on read.","Validate upstream that the producer never emits NaN/Infinity."],"exampleFix":"// before\nJsonObject o = new JsonObject(); o.addProperty(\"v\", Double.NaN);\nJsonTreeReader r = new JsonTreeReader(o);\nr.beginObject(); r.nextName();\nr.nextDouble(); // MalformedJsonException: JSON forbids NaN and infinities: NaN\n\n// after\nJsonTreeReader r = new JsonTreeReader(o);\nr.setLenient(true);\nr.beginObject(); r.nextName();\nr.nextDouble(); // returns NaN","handlingStrategy":"validation","validationCode":"// Sanitize NaN/Infinity in source doubles before building the tree\ndouble sanitize(double v) {\n  return Double.isNaN(v) || Double.isInfinite(v) ? 0.0d : v; // or use null wrapper\n}","typeGuard":"static boolean isJsonLegalDouble(double v) {\n  return !Double.isNaN(v) && !Double.isInfinite(v);\n}","tryCatchPattern":"JsonReader r = new JsonTreeReader(element);\nr.setLenient(true); // opt-in to NaN/Infinity if the source may contain them\ntry {\n  return r.nextDouble();\n} catch (MalformedJsonException e) {\n  if (e.getMessage() != null && e.getMessage().startsWith(\"JSON forbids NaN and infinities\")) {\n    throw new InvalidPayloadException(\"Numeric value not representable in strict JSON\", e);\n  }\n  throw e;\n}","preventionTips":["Filter NaN/Infinity at the producer when emitting strict JSON.","Enable setLenient(true) only on readers where non-standard numbers are expected.","Use a sentinel (null or a flag) instead of NaN/Infinity in JSON contracts."],"tags":["jsonreader","json-tree","number","lenient","spec"],"analyzedSha":"8b8628c65699bc4421696183c62ae0c1b9b281dc","analyzedAt":"2026-08-04T19:12:22.202Z","schemaVersion":2}