← All articles

Unexpected End of JSON Input: Why It Happens and How to Fix It

The parser hit the end of the string before the structure was complete. Causes range from truncated API responses to unclosed brackets and empty strings. Five patterns, five fixes.

SyntaxError: Unexpected end of JSON input means the parser reached the end of the string before the JSON structure was complete. The data was cut off. This article shows every common way that happens and exactly how to fix each one.

What the Error Means

JSON.parse() is a state machine. It reads characters one at a time, tracking open brackets, braces, and string delimiters. When it hits the end of the input string while still "inside" something — an object, an array, or a string — it throws:

SyntaxError: Unexpected end of JSON input

The error gives no line number or position because the problem is the absence of content — there is nothing to point at.

Cause 1 — Truncated API Response

The most common real-world cause. The server sent a large JSON body and either the network dropped the connection early, the response was read before it finished, or a proxy or CDN buffering limit was hit.

// What arrived (connection dropped mid-response):
'{"users":[{"id":1,"name":"Ada"},{"id":2,"na'

JSON.parse('{"users":[{"id":1,...') // SyntaxError: Unexpected end of JSON input

Fix: Check the HTTP status code and Content-Length header. Log the raw response body length before parsing. If you're using fetch, always await response.json() rather than reading response.text() and parsing manually — the browser's built-in JSON parser gives a clearer error on truncation.

// Correct
const data = await response.json();

// Brittle — hides truncation errors
const text = await response.text();
const data = JSON.parse(text);

Cause 2 — Unclosed Object or Array

The JSON was written by hand or generated by code that forgot a closing bracket or brace.

JSON.parse('{"name":"Ada","plan":"pro"')
// Missing closing }
// SyntaxError: Unexpected end of JSON input

JSON.parse('[1, 2, 3')
// Missing closing ]
// SyntaxError: Unexpected end of JSON input

Fix: Use a JSON linter or paste the string into JSON Fix — it identifies the unclosed delimiter and, in lenient mode, can add the missing bracket automatically.

Cause 3 — Unclosed String

A value string that was never terminated with a closing double-quote, often because the value itself contained a double-quote that wasn't escaped:

JSON.parse('{"title":"He said "hello" to her"}')
//                              ^ unescaped quote ends the string early
// SyntaxError: Unexpected end of JSON input

// Correct — escape inner quotes with backslash:
JSON.parse('{"title":"He said \"hello\" to her"}')

Fix: Escape internal double-quotes as \", or use JSON.stringify() to build the JSON in the first place rather than constructing strings by hand.

Cause 4 — Empty String

Passing an empty string or whitespace-only string to JSON.parse() throws the same error — there is no input to parse at all.

JSON.parse('')   // SyntaxError: Unexpected end of JSON input
JSON.parse('  ') // SyntaxError: Unexpected end of JSON input
JSON.parse()     // SyntaxError: Unexpected token u… (undefined cast to string)

This often happens when a form field, localStorage key, or environment variable is empty.

// Guard before parsing
const raw = localStorage.getItem('session');
if (!raw) return null;
return JSON.parse(raw);

Cause 5 — Streaming Response Read Too Early

When consuming a streaming API or WebSocket, it's easy to try to parse a chunk before the full message has arrived.

// ❌ Trying to parse an incomplete chunk
ws.onmessage = (event) => {
  const data = JSON.parse(event.data); // may be partial
};

// ✓ Buffer until the message boundary (application-level framing)
let buffer = '';
ws.onmessage = (event) => {
  buffer += event.data;
  if (buffer.endsWith('\n')) {        // or check for a known delimiter
    const data = JSON.parse(buffer.trim());
    buffer = '';
  }
};

Diagnose Truncation: Content-Length and the Streaming Reader

Two concrete techniques to confirm whether the response was actually cut short:

  • Compare against Content-Length. If the server set it, you can detect a short read directly:
    const res = await fetch(url);
    const expected = Number(res.headers.get('Content-Length') ?? NaN);
    const text = await res.text();
    if (Number.isFinite(expected) && text.length !== expected) {
      throw new Error(`truncated: got ${text.length} of ${expected} bytes`);
    }

    Note: Content-Length may be absent for chunked/compressed responses.

  • Read with the streaming body reader. Using res.body.getReader() lets you observe chunk-by-chunk arrival and notice when the stream closes mid-payload — which is the symptom of a dropped connection or proxy timeout. The browser surfaces the underlying network failure as a fetch rejection if the stream aborts; pair it with the parser error to be sure.

Quick Diagnosis Checklist

  • Log typeof input and input.length right before the parse call.
  • If the length looks too short, the response was truncated — check network logs.
  • If the length is 0, the source (API, storage, env var) returned nothing — add a guard.
  • If the length looks right, paste the string into JSON Fix to find the structural problem.

Recover Gracefully in Production

function safeParse(text, fallback = null) {
  if (!text || !text.trim()) return fallback;
  try {
    return JSON.parse(text);
  } catch {
    console.error('JSON parse failed, input length:', text.length);
    return fallback;
  }
}

Frequently Asked Questions

What causes "Unexpected end of JSON input"?

The parser reached the end of the string while still inside an object, array, or string — the data was incomplete. The most common real-world cause is a truncated API response; others are an unclosed bracket, an unterminated string, or an empty string.

Why is there no line or position number?

Because the problem is missing content, not a wrong character. There is nothing for the parser to point at — it simply ran out of input before the structure closed.

How do I fix it for an empty string?

Guard before parsing: if (!raw || !raw.trim()) return fallback;. Empty form fields, missing localStorage keys, and unset environment variables are the usual sources.

How do I handle it gracefully in production?

Wrap JSON.parse() in a safeParse helper that returns a fallback on failure (see the snippet above), and log the input length so you can tell truncation apart from malformed structure. For the full set of patterns, see handling broken JSON in JavaScript.

Fix Truncated JSON in Your Browser

Got a broken JSON string you need to inspect or repair? JSON Fix on fixjson.org parses, validates, and auto-repairs common structural errors — including missing brackets — directly in the browser with no data sent to any server.