Unexpected end of JSON input

Your code tried to read JSON from text that was empty or cut off, so the parser ran out of input before the data was complete.

Browser console
SyntaxError: Unexpected end of JSON input

Also appears as

  • SyntaxError: Failed to execute 'json' on 'Response': Unexpected end of JSON input
  • SyntaxError: JSON.parse: unexpected end of data at line 1 column 1 of the JSON data
  • SyntaxError: JSON Parse error: Unexpected EOF

Prompt to fix it

My app throws "SyntaxError: Unexpected end of JSON input". Find where it happens: a response.json() call on an empty response, or JSON.parse on an empty string. Check what the server actually sends for that request (status and body), including successful responses with no body, like 204, and error responses. Fix both sides: make the API return JSON wherever the client expects it, and make the client handle empty bodies and error statuses explicitly. Don’t use mode: "no-cors", and don’t hide the error with an empty catch.

Paste into Layerwise or any AI coding tool.

What it means

The JSON parser reached the end of the text before it found a complete value. Most of the time the text was empty: JSON.parse('') and response.json() on an empty body both throw this exact error.

Empty bodies are normal for some responses. A 204 No Content reply, a DELETE or PUT that returns nothing, and many error responses have no body at all. A request made with mode: 'no-cors' always gets an empty, unreadable body too.

The quick check is the Network tab: open the request and look at its Response panel. If it’s empty, the fix is on whichever side disagrees about the body. If it holds half a JSON document, the server crashed or timed out while sending it.

Common causes

  • The API returned an empty body, such as a 204 after a delete or update, and the code still calls response.json().
  • The server crashed or timed out partway through, or returned an error status with no body.
  • A server route never writes a body, for example a handler that calls res.end() or returns early.
  • The request uses mode: 'no-cors', which always produces an empty body.
  • The code parses an empty string read from localStorage, a cookie, or an environment variable.

How to fix it

  1. In the Network tab, open the request and check its status and Response panel.
  2. Read the body with response.text() and parse it only when it isn’t empty, or skip parsing for 204 responses.
  3. If the client expects JSON, make the API return a JSON body for both success and failure, even if it’s just {}.
  4. Remove mode: 'no-cors' and fix CORS on the server instead.
  5. Check stored values for an empty string before calling JSON.parse.

Example fix

export async function readJson<T>(response: Response): Promise<T | null> {
  const text = await response.text();
  if (!response.ok) {
    throw new Error(`Request failed with ${response.status}: ${text || '(empty body)'}`);
  }
  // 204 responses and some writes have no body.
  return text ? (JSON.parse(text) as T) : null;
}
All errors
SyntaxError: Unexpected token '<', "<!DOCTYPE "... is not valid JSON

Unexpected token '<', "<!DOCTYPE "... is not valid JSON

Your code expected JSON, but the server sent back an HTML page, usually a 404 page or your app’s own index.html.

Access to fetch at 'https://api.example.com/items' from origin 'http://localhost:5173' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

Blocked by CORS policy

The browser hid a response from another site because that server never said your site is allowed to read it.

POST https://my-app.com/api/checkout 500 (Internal Server Error)

500 Internal Server Error

The server’s code threw an error or crashed while handling the request, and the real error message is waiting in the server logs.

TypeError: Failed to fetch

Failed to fetch

The browser never got a usable response: the server was unreachable, or the browser blocked the request or its reply.

Build with an agent that checks its work

The Layerwise agent clicks through the live preview and reads the console, so it catches errors before you do.