Blog
3 min read

Unexpected End of JSON Input: Causes and Fixes

"SyntaxError: Unexpected end of JSON input" means you tried to parse JSON from an empty or cut-off string — most often calling response.json() on an empty response like a 204 or an error. How to find the real response, handle empty bodies safely, and fix the server side.

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

This error means JavaScript tried to parse JSON that stopped before it was complete — and very often, there was no JSON at all: an empty string.

JSON.parse('')        // Unexpected end of JSON input
JSON.parse('{"a":1')  // Unexpected end of JSON input (cut off)

Its cousin, Unexpected token < in JSON, means you got HTML instead of JSON. This one means you got nothing (or half of something).

The usual culprit: response.json() on an empty response

const res = await fetch('/api/items/42', { method: 'DELETE' })
const data = await res.json() // 💥

Many responses legitimately have no body:

  • 204 No Content — common for DELETE and some PUTs.
  • Error responses where the server sent a status code but no body.
  • Redirects and some HEAD requests.
  • A server that crashed halfway through the response.

Step 1: See what you actually got

In your browser's DevTools → Network tab, click the request and check Status and Response. Or log it:

const res = await fetch(url)
const text = await res.text()
console.log(res.status, JSON.stringify(text))

An empty "" confirms the diagnosis. (Browser Developer Tools for Beginners)

Step 2: Handle empty bodies safely

async function fetchJson(url, options) {
  const res = await fetch(url, options)
  if (!res.ok) {
    const message = await res.text()
    throw new Error(`HTTP ${res.status}: ${message || res.statusText}`)
  }
  if (res.status === 204) return null
  const text = await res.text()
  return text ? JSON.parse(text) : null
}

This checks res.ok first (so error pages don't get parsed as data), treats 204 as "no data", and only parses when there's something to parse.

Step 3: Fix the server if it should have sent JSON

If the endpoint is supposed to return data:

  • Make sure every code path sends the intended response. In Express, res.json(...) sends JSON even without return; returning prevents later code from trying to send another response. A branch that ends the response without calling a JSON response method can leave the body empty.
  • Return JSON for errors too, like { "error": "Not found" }, not an empty body.
  • Check for crashes. If the server dies mid-response, you get a truncated body. Look at the server logs. (500 Internal Server Error)

Other places it shows up

  • JSON.parse(localStorage.getItem('x')) when the key doesn't exist returns null, which parses fine — but an empty string '' doesn't. Guard it: JSON.parse(value || 'null').
  • Reading an empty or partially written file in Node.js, for example a config file another process is still writing.
  • Webhooks where the body was already consumed by middleware, leaving an empty stream. (Handle Webhooks Reliably)

The summary

  • You parsed an empty or cut-off string as JSON.
  • Usually response.json() on a 204, an error, or a crashed response.
  • Check res.ok, handle 204, parse only non-empty text, and make the server always return JSON.

EasySpawn keeps your frontend, API and logs on one server, so Claude Code can see both sides of a failed request and fix whichever one is wrong. See how it works or join the waitlist.

Related: What Is JSON? · Failed to Fetch · Fetch vs Axios · JavaScript Promises

Keep reading