NaN and Infinity in JSON

The JSON number grammar covers an optional minus sign, digits, an optional fraction and an optional exponent. NaN, Infinity and -Infinity match none of that, and JSON has no literal for them.

How the message appears

The same fault, worded by different engines. V8 (Chrome, Node, Edge) changed its format around Chrome 109, so older and newer runtimes disagree about the same document.

  • SyntaxError: Unexpected token 'N', ..."value": NaN}"... is not valid JSON
  • SyntaxError: JSON.parse: unexpected character at line 1 column 11 of the JSON data

What causes it

A serializer that emits the language’s own literals

Python’s json.dumps writes NaN and Infinity by default, which is valid Python and invalid JSON. Pass allow_nan=False to make it raise instead of producing a document other parsers reject.

A division or parse that produced NaN upstream

0/0, parseFloat("abc") and arithmetic on undefined all yield NaN. In JavaScript it then silently becomes null in the output, which is usually the real bug — a missing value that reads as a deliberate one.

Floating-point overflow

A number past roughly 1.8 × 10^308 becomes Infinity in IEEE-754 double precision. Very large integers hit a related problem: past 2^53 they lose precision silently on parse.

The fix

Use null for a value that has no number, and say so in your schema. If the distinction matters, encode it explicitly as a string — "NaN" — and convert on read.

Fails to parse
{
  "ratio": NaN,
  "limit": Infinity
}
Parses
{
  "ratio": null,
  "limit": null
}

The example travels in the URL fragment, which browsers never send to a server.

Worth knowing

  • JavaScript already does this for you: JSON.stringify({a: NaN}) returns {"a":null} rather than throwing.
  • JSON.stringify also drops undefined object properties entirely and converts undefined array elements to null, so an array can change meaning without changing length.

No cookies, no accounts, no tracking. Your JSON and text are processed entirely in your browser and never sent anywhere. We count anonymous page views (the page address only, nothing about you or your device), and use localStorage to remember your theme.