In Node 22 and Chrome 150, Unexpected end of JSON input has no position. It means the string was empty, whitespace, or still waiting for a value. Other truncations use a different sentence.
Unexpected end of JSON input comes from JSON.parse. In Node 22 and Chrome 150 the sentence has no position. An empty string, whitespace only, or a value the parser was still waiting for when the text ended, produces that sentence.
Not every truncated body uses that sentence. A lone { throws Expected property name or '}' in JSON at position 1 (line 1 column 2). {"a":1 throws Expected ',' or '}' after property value in JSON at position 6 (line 1 column 7). The position equals the string length, so there is no character there.
In Chrome 150, response.json() on an empty body says Failed to execute 'json' on 'Response': Unexpected end of JSON input. Read text() and check raw.length.
Paste the raw text into the JSON formatter. An empty string and whitespace-only text cannot be repaired. {"a": is repaired to {"a":null}. That null is filled in by the tool. It was not in the original text. For a complete sample, use the test data generator. If the first character is not JSON, see Unexpected token in JSON at position 0. A trailing comma such as {"a":1,} is covered in Expected double-quoted property name.
Python 3.9.6 does not use this sentence. An empty string is Expecting value: line 1 column 1 (char 0).
const raw = await response.text()
console.log(response.status, raw.length, JSON.stringify(raw.slice(-40)))
Input Node 22 / Chrome 150
'', spaces, or a newline Unexpected end of JSON input, no position
[, [1,, {"a": The same sentence
nul, tru, fals The same sentence
{ Expected property name or '}', position 1
{"a":1 Expected ',' or '}', position 6, equal to the length
[1 Expected ',' or ']', position 2, equal to the length
"hello Unterminated string in JSON
1. Unterminated fractional number in JSON
JSON.parse('')
JSON.parse(' ')
JSON.parse('\n')
// Unexpected end of JSON input
In Node 22, fetch of a 204 gives text() with length 0, and JSON.parse then throws this sentence. On that same Node, a 200 whose body is \n does too. Empty text, spaces, newlines, and tabs cannot be repaired. Do not parse an empty body. If the contract needs an object, return {} or [].
A comma, a colon, or [ was waiting for a value, and the text stopped:
JSON.parse('[')
JSON.parse('[1,')
JSON.parse('{"a":')
JSON.parse('{"a":[')
JSON.parse('{"a":{"b":')
// Unexpected end of JSON input
None of these include a position. One-click repair turns [ into [], [1, into [1], and {"a": into {"a":null}. That null was not sent by the server.
Complete null, true, and false parse. These prefixes do not:
JSON.parse('nul')
JSON.parse('tru')
JSON.parse('fals')
// Unexpected end of JSON input
n, nu, t, tr, f, fa, and fal throw the same sentence. Repair cannot finish those prefixes. Add the missing letters, or have the API send the whole value.
The body is unfinished here too, but the message is different. The position equals the string length, so the index is empty.
JSON.parse('{')
// Expected property name or '}' in JSON at position 1 (line 1 column 2)
JSON.parse('{"a":1')
// Expected ',' or '}' after property value in JSON at position 6 (line 1 column 7)
JSON.parse('[1')
// Expected ',' or ']' after array element in JSON at position 2 (line 1 column 3)
Repair closes the brackets: { becomes {}, {"a":1 becomes {"a":1}, and [1 becomes [1]. {"a":1, is an extra comma at the end. That message is Expected double-quoted property name, not this one. See Expected double-quoted property name.
JSON.parse('"hello')
// Unterminated string in JSON at position 6 (line 1 column 7)
JSON.parse('"')
// Unterminated string in JSON at position 1 (line 1 column 2)
The position is one past the last character. Repair only adds the missing ": "hello becomes "hello". It does not guess any further text.
These three are not Unexpected end of JSON input, and repair cannot fix them:
JSON.parse('-')
// No number after minus sign in JSON at position 1 (line 1 column 2)
JSON.parse('1.')
// Unterminated fractional number in JSON at position 2 (line 1 column 3)
JSON.parse('1e')
// Exponent part is missing a number in JSON at position 2 (line 1 column 3)
JSON.parse('1e+')
// Exponent part is missing a number in JSON at position 3 (line 1 column 4)
JSON.parse('-1') succeeds. A minus sign, a decimal point, or an exponent still needs its digits.
'' and ' ' are unrepairable in the formatter. A cut-off object is closed as above, and {"a": gains a null. nul, tru, fals, -, 1., and 1e are unrepairable too.
Read raw.length and the last 40 characters before you decide whether the body is empty, still waiting for a value, or a different error. If JSON.stringify throws, see Converting circular structure to JSON. For a payload that must parse, use the test data generator. The JSON formatter may insert null when it closes a bracket. Check that field after repair.
Related: JSON formatter ยท Blog index