What Is "Unexpected End of JSON Input"?
This JavaScript error from JSON.parse() means the input string ended before the JSON structure was complete. The parser was in the middle of reading an object, array, or string value and ran out of characters unexpectedly.
SyntaxError: Unexpected end of JSON inputIn Python the equivalent is: json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
In Go: unexpected end of JSON input from json.Unmarshal
Common Causes
Cause 1: Empty Response Body (Most Common)
Your server or API returned an empty response body — a 204 No Content, a 200 OK with no body, or a DELETE response. Calling .json() on an empty body always throws:
// Throws if body is empty:
const data = await response.json();
// Safe version:
const text = await response.text();
const data = text.trim() ? JSON.parse(text) : null;Cause 2: Truncated JSON from Network Issues
The response was cut off mid-transfer — network timeout, server crash during streaming, or a proxy with a small body size limit. The JSON is valid up to the cut-off point but incomplete:
{"users": [{"name": "Ravi", "age": 28}, {"name": "PriyThe parser reaches end-of-string while inside a string literal and throws. Diagnosis: check Content-Length vs actual bytes received — a mismatch confirms truncation.
Cause 3: Parsing null or undefined
const raw = localStorage.getItem("session"); // returns null if key missing
JSON.parse(raw); // TypeError or SyntaxError: null is not valid JSON
const value = someObject.field; // undefined if field doesn't exist
JSON.parse(value); // SyntaxErrorAlways guard:
const raw = localStorage.getItem("session");
const data = raw !== null ? JSON.parse(raw) : defaultValue;Cause 4: Empty String or Whitespace-Only String
JSON.parse(""); // SyntaxError: Unexpected end of JSON input
JSON.parse(" "); // same
JSON.parse("\n"); // sameThe smallest valid JSON values are: null, 0, "", true, false, [], {}
Cause 5: Incomplete JSON File Written to Disk
If a write operation was interrupted — server crash, disk-full event, process killed with SIGKILL — the JSON file on disk may be incomplete. The file ends mid-structure:
{"config": {"host": "localhost", "port": 543The file ends here — missing closing braces. The file is corrupt.
Check the last few bytes: a complete JSON object ends with }, a complete array ends with ]. If neither, the file is corrupt.
Cause 6: Content-Length Header Mismatch
The server sends a Content-Length header that is larger than the actual body. The HTTP client waits for the remaining bytes, times out, and returns a truncated body. Check in the Network tab — does the content-length match the actual received bytes?
Cause 7: Streaming Response Read Twice
In Node.js, once you call response.json() or response.text(), the body stream is consumed. Calling it again returns an empty body:
const response = await fetch(url);
const text = await response.text(); // consumes the body
const data = await response.json(); // throws — body already consumedFix: read the body once and parse manually:
const text = await response.text();
const data = JSON.parse(text);Diagnosing Network Truncation
async function fetchJSON(url) {
const response = await fetch(url);
if (response.status === 204) return null; // No Content — expected empty body
const text = await response.text();
if (!text.trim()) {
console.warn(`Empty body from ${url} (status: ${response.status})`);
return null;
}
// Check Content-Length vs actual received bytes
const contentLength = response.headers.get("content-length");
if (contentLength && parseInt(contentLength) !== text.length) {
console.warn(
`Possible truncation: Content-Length=${contentLength}, received=${text.length} bytes`
);
}
try {
return JSON.parse(text);
} catch (e) {
console.error(`JSON parse error from ${url}:`, e.message);
console.error(`Last 100 chars: ...${text.slice(-100)}`);
throw e;
}
}Safe Parse Utilities
JavaScript:
function safeJSON(str, fallback = null) {
if (str == null || !String(str).trim()) return fallback;
try {
return JSON.parse(str);
} catch (e) {
console.error("JSON parse failed:", e.message, "| Input:", String(str).slice(0, 100));
return fallback;
}
}
// localStorage pattern
function loadFromStorage(key, fallback = null) {
try {
const raw = localStorage.getItem(key);
return raw !== null ? JSON.parse(raw) : fallback;
} catch {
localStorage.removeItem(key); // clear corrupted data
return fallback;
}
}Python:
import json
def safe_json(text: str, fallback=None):
if not text or not text.strip():
return fallback
try:
return json.loads(text)
except json.JSONDecodeError as e:
print(f"JSON parse error: {e} | Input: {text[:100]!r}")
return fallbackGo:
func safeUnmarshal(data []byte, v interface{}) error {
if len(data) == 0 {
return nil // empty body — treat as no data, not an error
}
if err := json.Unmarshal(data, v); err != nil {
return fmt.Errorf("JSON parse failed: %w | last chars: %q",
err, data[max(0, len(data)-50):])
}
return nil
}When the JSON File on Disk Is Corrupt
- Check the last characters:
tail -c 10 data.json - Validate with
python3 -c "import json; json.load(open('data.json'))" - If corrupt, restore from backup or re-fetch from the source
- Add atomic write protection: write to a temp file then rename, so a crash mid-write never corrupts the original
Use JSONKit's JSON Validator to confirm that any JSON string you have is complete and valid before using it in your application.