[{"data":1,"prerenderedAt":1018},["ShallowReactive",2],{"blog-post-en-unexpected-end-of-json-input":3,"surround-\u002Fen\u002Fblog\u002Funexpected-end-of-json-input":1013},{"id":4,"title":5,"author":6,"body":7,"category":990,"date":991,"description":992,"draft":993,"extension":994,"h1":14,"image":995,"lastmod":991,"locales":996,"meta":998,"navigation":999,"path":1000,"promo":1001,"seo":1005,"stem":1006,"tags":1007,"__hash__":1012},"blog\u002Fen\u002Fblog\u002Funexpected-end-of-json-input.md","Unexpected End of JSON Input: Causes and Fixes","JSON Toolbox Team",{"type":8,"value":9,"toc":957},"minimark",[10,15,26,35,46,61,69,74,85,88,96,103,108,116,122,133,156,160,323,349,353,356,360,367,373,377,383,393,397,400,406,479,483,489,492,496,502,508,512,519,525,528,568,571,575,578,584,589,595,598,604,610,614,617,625,642,662,666,669,687,690,706,715,718,722,727,761,766,797,801,804,809,813,816,820,826,830,833,837,856,860,867,871,881,885,888,895,912,916],[11,12,14],"h1",{"id":13},"unexpected-end-of-json-input-what-it-means-and-how-to-fix-it","Unexpected End of JSON Input: What It Means and How to Fix It",[16,17,23],"pre",{"className":18,"code":20,"language":21,"meta":22},[19],"language-text","SyntaxError: Unexpected end of JSON input\n    at JSON.parse (\u003Canonymous>)\n","text","",[24,25,20],"code",{"__ignoreMap":22},[27,28,29,30,34],"p",{},"This error says one thing: ",[31,32,33],"strong",{},"the parser reached the end of the string while it was still expecting more."," It never found the closing piece it needed, so it gave up at the last character.",[27,36,37,38,41,42,45],{},"The useful part is that the message narrows the cause considerably. An empty API response, a truncated download, and a missing ",[24,39,40],{},"}"," are three different problems that need three different fixes — and on modern JavaScript engines they do not even produce the same message. This guide shows how to tell them apart in about a minute, and how to fix each one in ",[24,43,44],{},"fetch()",", Node.js, React, and file reads.",[47,48,49],"blockquote",{},[27,50,51,54,55,60],{},[31,52,53],{},"Paste it and see where it breaks:"," the ",[56,57,59],"a",{"href":58},"\u002Ftools\u002Fformat\u002Fjson-repair","JSON Repair"," tool fixes missing brackets, trailing commas, and quoting problems in your browser, and reports an error instead of guessing when a document cannot be recovered.",[27,62,63,64,68],{},"For the wider picture — ten parse errors, not just this one — see ",[56,65,67],{"href":66},"\u002Fblog\u002Fjson-parse-error-debug","JSON Parse Failed: 10 Common API Errors and How to Debug Them",".",[70,71,73],"h2",{"id":72},"what-does-unexpected-end-of-json-input-mean","What does \"Unexpected end of JSON input\" mean?",[27,75,76,84],{},[56,77,81],{"href":78,"rel":79},"https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FJavaScript\u002FReference\u002FGlobal_Objects\u002FJSON\u002Fparse",[80],"nofollow",[24,82,83],{},"JSON.parse()"," reads a string and expects exactly one complete JSON value. If the string ends before that value is finished, parsing fails.",[27,86,87],{},"On current V8 (Node 20+, Chrome, Edge), these all produce the message:",[16,89,94],{"className":90,"code":92,"language":93,"meta":22},[91],"language-js","JSON.parse('')        \u002F\u002F SyntaxError: Unexpected end of JSON input\nJSON.parse('   ')     \u002F\u002F SyntaxError: Unexpected end of JSON input\nJSON.parse('[1,')     \u002F\u002F SyntaxError: Unexpected end of JSON input\nJSON.parse('{\"a\":')   \u002F\u002F SyntaxError: Unexpected end of JSON input\nJSON.parse('tru')     \u002F\u002F SyntaxError: Unexpected end of JSON input\n","js",[24,95,92],{"__ignoreMap":22},[27,97,98,99,102],{},"The pattern: in every case the parser was ",[31,100,101],{},"expecting a value"," and the input ran out — the string was empty, it was only whitespace, or it ended right after a comma, a colon, or mid-literal.",[104,105,107],"h3",{"id":106},"when-you-get-a-different-message-instead","When you get a different message instead",[27,109,110,111,115],{},"A document that is cut off ",[112,113,114],"em",{},"after"," a complete value produces a different, more specific error with a position:",[16,117,120],{"className":118,"code":119,"language":93,"meta":22},[91],"JSON.parse('{\"a\": 1')      \u002F\u002F SyntaxError: Expected ',' or '}' after property value in JSON at position 7\nJSON.parse('[1, 2')        \u002F\u002F SyntaxError: Expected ',' or ']' after array element in JSON at position 5\nJSON.parse('{\"a\": \"bc')    \u002F\u002F SyntaxError: Unterminated string in JSON at position 9\nJSON.parse('{\"a\":1,')      \u002F\u002F SyntaxError: Expected double-quoted property name in JSON at position 7\n",[24,121,119],{"__ignoreMap":22},[27,123,124,125,128,129,132],{},"So if you are looking at exactly ",[24,126,127],{},"Unexpected end of JSON input"," on a current engine, suspect ",[31,130,131],{},"empty input"," first, not a missing brace. Two caveats:",[134,135,136,147],"ul",{},[137,138,139,142,143,146],"li",{},[31,140,141],{},"Older engines differ."," Before V8's improved JSON errors, a truncated document like ",[24,144,145],{},"{\"a\": 1"," also reported \"Unexpected end of JSON input\". If you are on an older runtime or see this message in a library's logs, a missing bracket is still a candidate.",[137,148,149,152,153,68],{},[31,150,151],{},"Other engines word it differently."," Firefox reports its own message, along the lines of ",[24,154,155],{},"JSON.parse: unexpected end of data at line 1 column 1",[70,157,159],{"id":158},"common-causes-at-a-glance","Common causes at a glance",[161,162,163,179],"table",{},[164,165,166],"thead",{},[167,168,169,173,176],"tr",{},[170,171,172],"th",{},"Cause",[170,174,175],{},"Typical symptom",[170,177,178],{},"How to confirm",[180,181,182,209,235,252,290,303],"tbody",{},[167,183,184,190,203],{},[185,186,187],"td",{},[31,188,189],{},"Empty response body",[185,191,192,195,196,199,200],{},[24,193,194],{},"204 No Content",", or an endpoint that returns nothing after a successful ",[24,197,198],{},"DELETE","\u002F",[24,201,202],{},"POST",[185,204,205,208],{},[24,206,207],{},"text.length === 0","; status is 204\u002F205",[167,210,211,216,226],{},[185,212,213],{},[31,214,215],{},"Whitespace-only body",[185,217,218,219,222,223],{},"Body is ",[24,220,221],{},"\" \""," or ",[24,224,225],{},"\"\\n\"",[185,227,228,231,232],{},[24,229,230],{},"text.trim().length === 0"," but ",[24,233,234],{},"text.length > 0",[167,236,237,242,245],{},[185,238,239],{},[31,240,241],{},"Truncated response",[185,243,244],{},"Timeout, proxy buffer limit, body-size cap killed the transfer",[185,246,247,248,251],{},"Received bytes \u003C ",[24,249,250],{},"Content-Length","; ends mid-value",[167,253,254,259,272],{},[185,255,256],{},[31,257,258],{},"Unclosed structure in hand-written JSON",[185,260,261,262,264,265,268,269],{},"Missing ",[24,263,40],{},", ",[24,266,267],{},"]",", or closing ",[24,270,271],{},"\"",[185,273,274,275,264,278,264,281,264,283,286,287],{},"Ends with ",[24,276,277],{},"{",[24,279,280],{},"[",[24,282,271],{},[24,284,285],{},",",", or ",[24,288,289],{},":",[167,291,292,297,300],{},[185,293,294],{},[31,295,296],{},"File read before the write finished",[185,298,299],{},"Non-atomic write, or reading a streamed file too early",[185,301,302],{},"Retry the read and it works; file grows between reads",[167,304,305,313,316],{},[185,306,307],{},[31,308,309,310],{},"Parsing ",[24,311,312],{},"undefined",[185,314,315],{},"Value came from a missing variable or an unset field",[185,317,318,319,322],{},"Message is ",[24,320,321],{},"\"undefined\" is not valid JSON",", not this one",[27,324,325,326,329,330,333,334,337,338,341,342,344,345,348],{},"One counter-intuitive case worth knowing: ",[24,327,328],{},"JSON.parse(null)"," does ",[31,331,332],{},"not"," throw — ",[24,335,336],{},"null"," is coerced to the string ",[24,339,340],{},"\"null\""," and parses to ",[24,343,336],{},". ",[24,346,347],{},"JSON.parse(undefined)"," throws, but with a different message.",[70,350,352],{"id":351},"how-to-debug-empty-vs-truncated-vs-unclosed","How to debug: empty vs truncated vs unclosed",[27,354,355],{},"Work through these in order. Each step eliminates one of the three causes.",[104,357,359],{"id":358},"step-1-read-the-text-not-the-parsed-value","Step 1: Read the text, not the parsed value",[27,361,362,363,366],{},"Never debug this error through ",[24,364,365],{},"res.json()"," — it parses before you can look at anything. Read the body as text first:",[16,368,371],{"className":369,"code":370,"language":93,"meta":22},[91],"const res = await fetch(url)\nconst text = await res.text()\nconsole.log('status:', res.status, '| length:', text.length)\n",[24,372,370],{"__ignoreMap":22},[104,374,376],{"id":375},"step-2-is-it-empty","Step 2: Is it empty?",[16,378,381],{"className":379,"code":380,"language":93,"meta":22},[91],"if (text.trim().length === 0) {\n  \u002F\u002F Empty or whitespace-only: this is the classic cause of the message.\n  console.log('empty body, status', res.status)\n}\n",[24,382,380],{"__ignoreMap":22},[27,384,385,388,389,392],{},[24,386,387],{},"length === 0"," means no body at all. ",[24,390,391],{},"trim().length === 0"," with a non-zero length means whitespace only — a surprisingly common outcome when a server writes a newline.",[104,394,396],{"id":395},"step-3-inspect-the-tail","Step 3: Inspect the tail",[27,398,399],{},"The last characters tell you which failure you have:",[16,401,404],{"className":402,"code":403,"language":93,"meta":22},[91],"console.log(JSON.stringify(text.slice(-80)))\n",[24,405,403],{"__ignoreMap":22},[161,407,408,418],{},[164,409,410],{},[167,411,412,415],{},[170,413,414],{},"Ends with",[170,416,417],{},"What it means",[180,419,420,431,442,453,465],{},[167,421,422,428],{},[185,423,424,264,426],{},[24,425,277],{},[24,427,280],{},[185,429,430],{},"The structure was opened and never closed",[167,432,433,439],{},[185,434,435,438],{},[24,436,437],{},"\"a"," (an odd number of unescaped quotes)",[185,440,441],{},"A string was left unterminated",[167,443,444,450],{},[185,445,446,222,448],{},[24,447,285],{},[24,449,289],{},[185,451,452],{},"A value was expected and never arrived",[167,454,455,458],{},[185,456,457],{},"A complete value but no closing bracket",[185,459,261,460,222,462,464],{},[24,461,40],{},[24,463,267],{}," — usually a different error message with a position",[167,466,467,476],{},[185,468,469,470,222,473],{},"Mid-token, e.g. ",[24,471,472],{},"tru",[24,474,475],{},"12.",[185,477,478],{},"The document was cut off mid-value",[104,480,482],{"id":481},"step-4-compare-received-bytes-with-content-length","Step 4: Compare received bytes with Content-Length",[16,484,487],{"className":485,"code":486,"language":93,"meta":22},[91],"const declared = res.headers.get('content-length')\nconsole.log('declared:', declared, '| received:', new TextEncoder().encode(text).length)\n",[24,488,486],{"__ignoreMap":22},[27,490,491],{},"If you received fewer bytes than declared, the response was truncated in transit — a timeout, a proxy buffer limit, or a body-size cap. Re-fetch; do not try to parse half a document.",[104,493,495],{"id":494},"step-5-classify-it-automatically","Step 5: Classify it automatically",[27,497,498,499,501],{},"Run this only after ",[24,500,83],{}," has already failed — it classifies the tail of a broken string, it does not tell you whether a document is valid.",[16,503,506],{"className":504,"code":505,"language":93,"meta":22},[91],"function inspectJsonFailure(text) {\n  const trimmed = text.trim()\n\n  if (trimmed.length === 0) {\n    return { kind: 'empty', detail: 'The input is empty or whitespace only.' }\n  }\n\n  const last = trimmed[trimmed.length - 1]\n  if ('{[\",:'.includes(last)) {\n    return { kind: 'unclosed', detail: `Input ends with \"${last}\" — a value or closing bracket is missing.` }\n  }\n\n  return { kind: 'truncated', detail: 'Input ends mid-value. Compare received bytes with Content-Length.' }\n}\n",[24,507,505],{"__ignoreMap":22},[70,509,511],{"id":510},"how-to-fix-it-in-fetch","How to fix it in fetch()",[27,513,514,515,518],{},"The fix is to stop calling ",[24,516,517],{},".json()"," blindly. Read the text, handle the empty case, check the content type, then parse:",[16,520,523],{"className":521,"code":522,"language":93,"meta":22},[91],"async function fetchJson(url, init) {\n  const res = await fetch(url, init)\n  const text = await res.text()\n\n  \u002F\u002F 204 No Content and 205 Reset Content have no body by definition.\n  if (res.status === 204 || res.status === 205 || text.trim() === '') {\n    return null\n  }\n\n  const type = res.headers.get('content-type') || ''\n  if (!type.includes('application\u002Fjson')) {\n    throw new Error(`Expected JSON from ${url}, got \"${type || 'no content-type'}\"`)\n  }\n\n  try {\n    return JSON.parse(text)\n  } catch (err) {\n    throw new Error(`Invalid JSON from ${url} (${text.length} bytes): ${err.message}`)\n  }\n}\n",[24,524,522],{"__ignoreMap":22},[27,526,527],{},"Three details that matter:",[529,530,531,553,562],"ol",{},[137,532,533,541,542,544,545,552],{},[31,534,535,538,539],{},[24,536,537],{},"res.text()"," then ",[24,540,83],{},", not ",[24,543,365],{},". You cannot inspect a body you already parsed — and ",[56,546,549],{"href":547,"rel":548},"https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FAPI\u002FResponse\u002Fjson",[80],[24,550,551],{},"Response.json()"," throws before you get a chance.",[137,554,555,558,559,561],{},[31,556,557],{},"A 204 is a success."," Do not treat it as an error; return ",[24,560,336],{}," (or whatever your code uses for \"no content\").",[137,563,564,567],{},[31,565,566],{},"Check the content type."," An HTML error page from a proxy returns 200 and parses as neither JSON nor an empty string — it fails with a different message, and this check makes the real problem obvious.",[27,569,570],{},"For truncated responses, the fix is not parsing: it is raising timeouts, lifting proxy body limits, or paginating the endpoint.",[70,572,574],{"id":573},"how-to-fix-it-in-nodejs","How to fix it in Node.js",[27,576,577],{},"Reading a file:",[16,579,582],{"className":580,"code":581,"language":93,"meta":22},[91],"import { readFile } from 'node:fs\u002Fpromises'\n\nconst text = await readFile('data.json', 'utf8')\n\nif (text.trim() === '') {\n  throw new Error('data.json is empty — the write did not complete')\n}\n\nconst data = JSON.parse(text)\n",[24,583,581],{"__ignoreMap":22},[27,585,586,587,289],{},"Parsing a request body — note that an empty body arrives as an empty string, not as ",[24,588,312],{},[16,590,593],{"className":591,"code":592,"language":93,"meta":22},[91],"\u002F\u002F Express\napp.post('\u002Fwebhook', express.json(), (req, res) => {\n  \u002F\u002F req.body is {} when the body is empty, not undefined\n  if (!req.body || Object.keys(req.body).length === 0) {\n    return res.status(400).json({ error: 'EMPTY_BODY' })\n  }\n  \u002F\u002F ...\n})\n",[24,594,592],{"__ignoreMap":22},[27,596,597],{},"Reading JSON that another process is still writing is the subtle version of this bug. Write atomically so a reader never sees a half-written file:",[16,599,602],{"className":600,"code":601,"language":93,"meta":22},[91],"import { writeFile, rename } from 'node:fs\u002Fpromises'\n\nconst target = 'data.json'\nconst tmp = `${target}.tmp`\n\nawait writeFile(tmp, JSON.stringify(data, null, 2), 'utf8')\nawait rename(tmp, target) \u002F\u002F atomic on the same filesystem\n",[24,603,601],{"__ignoreMap":22},[27,605,606,609],{},[24,607,608],{},"rename"," is atomic within a filesystem, so a concurrent reader sees either the old file or the new one — never a partial one.",[70,611,613],{"id":612},"how-to-fix-it-in-react-and-other-frontend-code","How to fix it in React and other frontend code",[27,615,616],{},"The usual cause in a component is parsing during the first render, before data exists — or parsing an empty response from an endpoint that returns nothing:",[16,618,623],{"className":619,"code":621,"language":622,"meta":22},[620],"language-jsx","function ItemList() {\n  const [items, setItems] = useState([])\n  const [error, setError] = useState(null)\n\n  useEffect(() => {\n    let cancelled = false\n\n    ;(async () => {\n      try {\n        const res = await fetch('\u002Fapi\u002Fitems')\n        const text = await res.text()\n\n        if (cancelled) return\n\n        if (text.trim() === '') {\n          setItems([])          \u002F\u002F no content is a valid outcome, not an error\n          return\n        }\n\n        setItems(JSON.parse(text))\n      } catch (err) {\n        if (!cancelled) setError(err)\n      }\n    })()\n\n    return () => { cancelled = true }\n  }, [])\n\n  if (error) return \u003Cp>Failed to load: {error.message}\u003C\u002Fp>\n  return \u003Cul>{items.map((i) => \u003Cli key={i.id}>{i.name}\u003C\u002Fli>)}\u003C\u002Ful>\n}\n","jsx",[24,624,621],{"__ignoreMap":22},[27,626,627,628,637,638,641],{},"Two habits prevent most of these: ",[31,629,630,631,634,635],{},"never call ",[24,632,633],{},"JSON.parse"," on a value that might be ",[24,636,312],{},", and ",[31,639,640],{},"never parse during render"," — parse inside the effect or the loader, after you have confirmed the text exists.",[27,643,644,645,648,649,652,653,655,656,658,659,661],{},"If the JSON comes from ",[24,646,647],{},"localStorage",", the same rule applies: ",[24,650,651],{},"localStorage.getItem(key)"," returns ",[24,654,336],{}," when the key is missing, and ",[24,657,328],{}," quietly returns ",[24,660,336],{}," instead of the object you expected.",[70,663,665],{"id":664},"validate-and-repair-the-json-in-your-browser","Validate and repair the JSON in your browser",[27,667,668],{},"When you have the text in front of you, two tools finish the job:",[27,670,671,675,676,679,680,222,683,686],{},[31,672,673],{},[56,674,59],{"href":58}," — fixes trailing commas, single quotes, unquoted keys, ",[31,677,678],{},"missing closing brackets",", comments, and Python\u002FJS constants such as ",[24,681,682],{},"True",[24,684,685],{},"NaN",". It applies best-effort fixes, then parses the result to confirm it is valid before showing it.",[27,688,689],{},"Two limits to keep in mind, both stated on the tool page:",[134,691,692,699],{},[137,693,694,695,698],{},"It ",[31,696,697],{},"cannot invent missing data",". Closing a bracket is recoverable; a document whose middle was cut off is not.",[137,700,701,702,705],{},"If the structure cannot be recovered, it ",[31,703,704],{},"reports an error instead of returning partial output",". That is the correct outcome for a truncated response — get the full data instead.",[27,707,708,714],{},[31,709,710],{},[56,711,713],{"href":712},"\u002Ftools\u002Fformat\u002Fjson-editor","JSON Editor"," — paste or open the file to get live syntax validation with the error position, then format or minify. Use it to confirm a hand-written file is complete before your application reads it.",[27,716,717],{},"Both run in your browser, so the payload is not uploaded — which matters when the broken JSON is a production API response.",[70,719,721],{"id":720},"how-to-prevent-the-error","How to prevent the error",[27,723,724],{},[31,725,726],{},"Server side:",[134,728,729,739,749,755],{},[137,730,731,734,735,738],{},[31,732,733],{},"Always return valid JSON, including errors."," ",[24,736,737],{},"{\"error\": {...}}"," is far easier to debug than an empty 500.",[137,740,741,748],{},[31,742,743,744,747],{},"Do not set ",[24,745,746],{},"Content-Type: application\u002Fjson"," on a 204."," If there is no body, say so with the status code and no content type.",[137,750,751,754],{},[31,752,753],{},"Set explicit timeouts and body-size limits"," so a truncation fails loudly with a status code instead of silently cutting a document in half.",[137,756,757,760],{},[31,758,759],{},"Write files atomically"," (temp file + rename) so no reader ever sees a partial file.",[27,762,763],{},[31,764,765],{},"Client side:",[134,767,768,776,785,791],{},[137,769,770,734,773,68],{},[31,771,772],{},"Guard before parsing:",[24,774,775],{},"if (text && text.trim() !== '') { JSON.parse(text) }",[137,777,778,784],{},[31,779,780,781,783],{},"Wrap ",[24,782,83],{}," in try\u002Fcatch"," and include the length and the tail of the string in the error message — that is the information you will need later.",[137,786,787,790],{},[31,788,789],{},"Treat \"no content\" as a normal outcome"," for endpoints that can legitimately return nothing.",[137,792,793,796],{},[31,794,795],{},"Log the offending payload safely:"," log length, status, and a truncated tail, not the whole body, which may contain tokens or personal data.",[70,798,800],{"id":799},"faq","FAQ",[104,802,73],{"id":803},"what-does-unexpected-end-of-json-input-mean-1",[27,805,806,808],{},[24,807,83],{}," reached the end of the string while still expecting more content. On current engines that most often means the input was empty or whitespace-only, or ended right after a comma, colon, or mid-literal.",[104,810,812],{"id":811},"is-this-error-always-caused-by-an-empty-response","Is this error always caused by an empty response?",[27,814,815],{},"No, but on modern V8 an empty or whitespace-only string is the most common cause of this exact wording. A document with a missing closing bracket usually produces a different message that includes a character position — unless you are on an older engine, which reported the same message for both.",[104,817,819],{"id":818},"how-do-i-know-if-the-response-is-truncated","How do I know if the response is truncated?",[27,821,822,823,825],{},"Compare the bytes you received with the ",[24,824,250],{}," header, and look at the last ~80 characters. If the document stops mid-value, or you received fewer bytes than declared, it was truncated — re-fetch rather than trying to parse it.",[104,827,829],{"id":828},"can-this-error-happen-with-otherwise-valid-json","Can this error happen with otherwise valid JSON?",[27,831,832],{},"Yes — if only part of a valid document arrived. A 400 KB response cut off at 300 KB is \"valid JSON\" that was never fully delivered. The other case is a file you read while it was still being written.",[104,834,836],{"id":835},"how-do-i-fix-it-in-fetch","How do I fix it in fetch?",[27,838,839,840,842,843,845,846,264,849,852,853,855],{},"Do not call ",[24,841,365],{}," directly. Read ",[24,844,537],{},", return early for ",[24,847,848],{},"204",[24,850,851],{},"205",", or an empty body, verify the content type, then ",[24,854,83],{}," inside a try\u002Fcatch that reports the length and tail of the text.",[104,857,859],{"id":858},"how-do-i-fix-it-in-react","How do I fix it in React?",[27,861,862,863,866],{},"Parse inside the effect or loader, not during render, and only after confirming the text exists. Handle the empty-body case explicitly instead of letting ",[24,864,865],{},"JSON.parse('')"," throw on every render.",[104,868,870],{"id":869},"how-do-i-fix-it-in-nodejs","How do I fix it in Node.js?",[27,872,873,874,877,878,880],{},"Check for an empty string after ",[24,875,876],{},"fs.readFile",", and write files atomically (temp file + ",[24,879,608],{},") so a concurrent read never sees half a file.",[104,882,884],{"id":883},"can-an-online-tool-repair-truncated-json","Can an online tool repair truncated JSON?",[27,886,887],{},"It can repair documents with recoverable syntax problems — missing closing brackets, trailing commas, quoting issues. It cannot restore data that never arrived. For a truncated response, re-fetch from the source.",[104,889,891,892,894],{"id":890},"why-does-jsonparsenull-not-throw","Why does ",[24,893,328],{}," not throw?",[27,896,897,898,337,900,902,903,905,906,908,909,911],{},"Because ",[24,899,336],{},[24,901,340],{},", which is valid JSON. It returns ",[24,904,336],{},". This silently masks missing values, so check for ",[24,907,336],{}," before parsing values from ",[24,910,647],{}," or optional fields.",[70,913,915],{"id":914},"whats-next","What's Next?",[134,917,918,926,934,942],{},[137,919,920,923,924,68],{},[31,921,922],{},"Have the broken text?"," Paste it into ",[56,925,59],{"href":58},[137,927,928,931,932,68],{},[31,929,930],{},"Need the error position?"," Validate it in the ",[56,933,713],{"href":712},[137,935,936,939,940,68],{},[31,937,938],{},"Other parse errors?"," Read ",[56,941,67],{"href":66},[137,943,944,947,948,952,953,68],{},[31,945,946],{},"Suspect the file itself?"," See ",[56,949,951],{"href":950},"\u002Fblog\u002Fhow-to-open-json-file","How to Open, View, and Edit a JSON File"," and ",[56,954,956],{"href":955},"\u002Fblog\u002Fhow-to-create-json-file","How to Create a JSON File",{"title":22,"searchDepth":958,"depth":958,"links":959},2,[960,964,965,972,973,974,975,976,977,989],{"id":72,"depth":958,"text":73,"children":961},[962],{"id":106,"depth":963,"text":107},3,{"id":158,"depth":958,"text":159},{"id":351,"depth":958,"text":352,"children":966},[967,968,969,970,971],{"id":358,"depth":963,"text":359},{"id":375,"depth":963,"text":376},{"id":395,"depth":963,"text":396},{"id":481,"depth":963,"text":482},{"id":494,"depth":963,"text":495},{"id":510,"depth":958,"text":511},{"id":573,"depth":958,"text":574},{"id":612,"depth":958,"text":613},{"id":664,"depth":958,"text":665},{"id":720,"depth":958,"text":721},{"id":799,"depth":958,"text":800,"children":978},[979,980,981,982,983,984,985,986,987],{"id":803,"depth":963,"text":73},{"id":811,"depth":963,"text":812},{"id":818,"depth":963,"text":819},{"id":828,"depth":963,"text":829},{"id":835,"depth":963,"text":836},{"id":858,"depth":963,"text":859},{"id":869,"depth":963,"text":870},{"id":883,"depth":963,"text":884},{"id":890,"depth":963,"text":988},"Why does JSON.parse(null) not throw?",{"id":914,"depth":958,"text":915},"json_tools","2026-10-04T00:00:00.000Z","Unexpected end of JSON input: the parser ran out of text too early. Diagnose empty, truncated, or unclosed JSON, then fix it in fetch, Node, and files.",false,"md","\u002Fblog\u002Fcover\u002Fen\u002Funexpected-end-of-json-input-cover.svg",[997],"en",{},true,"\u002Fen\u002Fblog\u002Funexpected-end-of-json-input",{"slug":1002,"text":1003,"btn":1004},"json-repair","Paste the broken JSON and repair it in your browser:","Open JSON Repair",{"title":5,"description":992},"en\u002Fblog\u002Funexpected-end-of-json-input",[1008,633,1009,1010,1011],"JSON","Debugging","JavaScript","API","AecV3R5yHNO1d9xSwwnz4gsfg4nZiUl8CveDlDsd3LM",[1014,1015],null,{"path":1016,"title":1017},"\u002Fen\u002Fblog\u002Fhow-to-create-manifest-json","How to Create a manifest.json File: PWA & Chrome Examples",1791273861848]