NaN is not valid JSON
`NaN` has no representation in JSON. It appears when a language serialises a floating-point not-a-number without checking — Python's `json.dumps` emits it by default, and so do several numeric libraries.
The input
{"a": NaN}{"a": null}How to fix it
Emit `null` instead, or a sentinel your consumer understands. In Python, pass `allow_nan=False` to `json.dumps` so the problem surfaces at write time rather than at read time in someone else's service.
Python's json module both writes and reads NaN by default, so a round trip inside Python succeeds while every other language rejects the output. That asymmetry is why this reaches production.
What each parser reports
Every message below was captured by running this exact input through the parser named. 14 of 21 parsers rejected it; 7 accepted it.
| Parser | Exact message |
|---|---|
| CPython json.loads CPython 3.12.3 | accepted — no error |
| encoding/json Unmarshal Go go1.22.2 | invalid character 'N' looking for beginning of valuewhat this message means → |
| Gson Java 21.0.12 | accepted — no error |
| Gson JsonParser (lenient off) Java 21.0.12 | accepted — no error |
| hjson Node.js 22.22.2 | End of input while parsing an object (missing '}') at line 1,10 >>>"a": NaN} ...what this message means → |
| Jackson ObjectMapper Java 21.0.12 | Non-standard token 'NaN': enable `JsonReadFeature.ALLOW_NON_NUMERIC_NUMBERS` to allowwhat this message means → |
| JavaScriptCore JSON.parse JavaScriptCore (Bun 1.4.1) | JSON Parse error: Unexpected identifier "NaN"what this message means → |
| json-bigint Node.js 22.22.2 | Unexpected 'N' |
| JSON5 Node.js 22.22.2 | accepted — no error |
| JSON::PP Perl 5.038002 | malformed JSON string, neither array, object, number, string or atom, at character offset 6 (before "NaN}")what this message means → |
| json_decode PHP 8.3.6 | Syntax error |
| Newtonsoft.Json JsonConvert Newtonsoft.Json 13.0.3 on .NET 8.0.30 | accepted — no error |
| Newtonsoft.Json JsonTextReader Newtonsoft.Json 13.0.3 on .NET 8.0.30 | accepted — no error |
| orjson CPython 3.12.3 | unexpected character, expected a JSON value: line 1 column 7 (char 6)what this message means → |
| Ruby JSON.parse Ruby 3.2.3 | unexpected token at 'NaN}' |
| serde_json::from_str Rust (serde_json 1.x) | expected value at line 1 column 7what this message means → |
| SpiderMonkey JSON.parse SpiderMonkey 115 | JSON.parse: unexpected character at line 1 column 7 of the JSON datawhat this message means → |
| System.Text.Json Deserialize .NET 8.0.30 | 'N' is an invalid start of a value. Path: $ | LineNumber: 0 | BytePositionInLine: 6.what this message means → |
| System.Text.Json JsonDocument .NET 8.0.30 | 'N' is an invalid start of a value. LineNumber: 0 | BytePositionInLine: 6.what this message means → |
| ujson CPython 3.12.3 | accepted — no error |
| V8 JSON.parse Node.js 22.22.2 | Unexpected token 'N', "{"a": NaN}" is not valid JSONwhat this message means → |
What the specification says
The exact sections that govern this error. Descriptions are our paraphrase; follow the links for the normative text.
| Body | Section |
|---|---|
| IETF | A number is base 10, optionally signed with a minus, with an optional fraction and exponent. The section states that leading zeros are not allowed, and that values which cannot be represented in its grammar — Infinity and NaN among them — are not permitted. |
| Ecma International | A number is decimal digits with no superfluous leading zero. Values such as Infinity and NaN are not permitted. |
| IEEE | Referenced by RFC 8259 §6 as the basis for its interoperability guidance on numbers. |
Peer-reviewed literature
- D. Goldberg, “What every computer scientist should know about floating-point arithmetic”, ACM Computing Surveys, vol. 23, no. 1, pp. 5–48, 1991. doi:10.1145/103162.103163
Other errors in this category
Infinity is not valid JSON
Same root cause as NaN — a float overflowed and the serialiser wrote `Infinity` or `-Infinity`, which the JSON grammar has no toke…
undefined is not valid JSON
`undefined` is a JavaScript value with no JSON equivalent. `JSON.stringify` normally drops undefined object properties, so seeing …
Python True / False / None in JSON
Python's `repr` of a dict writes `True`, `False` and `None`. JSON requires the lowercase `true`, `false` and `null`.…