<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: mergejsonfiles</title>
    <description>The latest articles on DEV Community by mergejsonfiles (@mergejsonfiles_1ea51046a1).</description>
    <link>https://dev.to/mergejsonfiles_1ea51046a1</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4032667%2F3a95c83d-f71f-4c55-a246-0e8c07ea64b9.png</url>
      <title>DEV Community: mergejsonfiles</title>
      <link>https://dev.to/mergejsonfiles_1ea51046a1</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mergejsonfiles_1ea51046a1"/>
    <language>en</language>
    <item>
      <title>Every JSON error message, decoded</title>
      <dc:creator>mergejsonfiles</dc:creator>
      <pubDate>Thu, 16 Jul 2026 19:01:58 +0000</pubDate>
      <link>https://dev.to/mergejsonfiles_1ea51046a1/every-json-error-message-decoded-2mfp</link>
      <guid>https://dev.to/mergejsonfiles_1ea51046a1/every-json-error-message-decoded-2mfp</guid>
      <description>&lt;p&gt;JSON parsers are strict, and their error messages are famously unhelpful. You get a position number and a vague noun. The actual mistake is usually somewhere else entirely.&lt;/p&gt;

&lt;p&gt;This is a reference for the messages you actually see, what causes each one, and — the part nobody tells you — why the position they report is often a lie.&lt;/p&gt;

&lt;p&gt;Why the position is usually wrong&lt;br&gt;
Start here, because it explains most of the confusion.&lt;/p&gt;

&lt;p&gt;A parser reports where it gave up, not where you made the mistake. Those are different places, sometimes by hundreds of lines.&lt;/p&gt;

&lt;p&gt;{&lt;br&gt;
  "a": 1,&lt;br&gt;
  "b": 2,&lt;br&gt;
}&lt;br&gt;
The mistake is the comma after 2. The parser is fine with that comma at the time — a comma legitimately means "another key is coming". It only fails when it reaches } and finds no key. So it blames the }, one character past the real problem.&lt;/p&gt;

&lt;p&gt;The rule: the error position is where the parser's expectation broke, which is at or after your typo, never before. So when you get a position, look backwards from it.&lt;/p&gt;

&lt;p&gt;The messages&lt;br&gt;
Unexpected token } in JSON at position N&lt;br&gt;
Almost always a trailing comma — the case above. Look at the character just before position N. If it's a comma, that's your bug.&lt;/p&gt;

&lt;p&gt;Same message with ] instead of } is a trailing comma in an array.&lt;/p&gt;

&lt;p&gt;Unexpected end of JSON input&lt;br&gt;
The document ended while something was still open. Two very different causes:&lt;/p&gt;

&lt;p&gt;An unclosed bracket or brace. Every { needs }, every [ needs ].&lt;br&gt;
Truncation. The file or response is genuinely incomplete — a fetch that failed halfway, a log line cut at a length limit, or an LLM that hit its token cap mid-object.&lt;br&gt;
Worth distinguishing, because cause 2 means data is missing, not malformed. Adding a } to make it parse gives you valid JSON with a chunk of your records gone.&lt;/p&gt;

&lt;p&gt;Special case: this is also what you get from JSON.parse(""). An empty string is not valid JSON. If you're parsing a fetch response, an empty body throws exactly this — and the real problem is a 204 or a failed request, not your JSON.&lt;/p&gt;

&lt;p&gt;Unexpected token ' in JSON at position 1&lt;br&gt;
Single quotes. That's a Python dict or a JS object literal, not JSON:&lt;/p&gt;

&lt;p&gt;{'name': 'Ada'}&lt;br&gt;
JSON requires double quotes on both keys and string values. No exceptions, no config flag.&lt;/p&gt;

&lt;p&gt;Unexpected token o in JSON at position 1&lt;br&gt;
My favourite, because it looks cryptic and isn't. You did this:&lt;/p&gt;

&lt;p&gt;JSON.parse(someObject)&lt;br&gt;
someObject is already an object. JSON.parse needs a string, so JS coerces it — giving "[object Object]". The parser reads [, expects a value, and finds o.&lt;/p&gt;

&lt;p&gt;Your JSON is fine. You just parsed something that was never a string. Usually this means a library (axios, most fetch wrappers) already parsed it for you.&lt;/p&gt;

&lt;p&gt;The [object Object] tell also shows up as Unexpected token o at position 1 in a lot of stack traces where people spend an hour debugging their payload. Don't.&lt;/p&gt;

&lt;p&gt;Unexpected token &amp;lt; in JSON at position 0&lt;br&gt;
The server sent you HTML, not JSON. That &amp;lt; is the start of &amp;lt;!DOCTYPE html&amp;gt; or .&lt;/p&gt;

&lt;p&gt;You are parsing an error page. A 404, a 500, a login redirect, a Cloudflare challenge, or a proxy's error output. Log the raw response text and you'll see it instantly. Nothing about your parsing code is broken — check the status code before you parse.&lt;/p&gt;

&lt;p&gt;Unexpected token n in JSON at position N&lt;br&gt;
Usually NaN, sometimes None, occasionally a bare nan. JSON has null and nothing else for absence. NaN and Infinity are valid JavaScript numbers and valid Python floats but they are not valid JSON — which is why JSON.stringify({x: NaN}) quietly gives you {"x":null}.&lt;/p&gt;

&lt;p&gt;None specifically means Python got involved somewhere — someone str()'d a dict instead of json.dumps'ing it.&lt;/p&gt;

&lt;p&gt;Unexpected token T in JSON at position N&lt;br&gt;
True or False with a capital letter. Python again. JSON booleans are lowercase.&lt;/p&gt;

&lt;p&gt;Expecting property name enclosed in double quotes (Python)&lt;br&gt;
Python's version of the trailing comma error, and it's clearer than JavaScript's — it tells you it wanted a key and didn't get one. Same fix: look for the comma before the closing brace.&lt;/p&gt;

&lt;p&gt;It also fires for unquoted keys:&lt;/p&gt;

&lt;p&gt;{name: "Ada"}&lt;br&gt;
Keys are strings. They get quotes.&lt;/p&gt;

&lt;p&gt;Expecting value: line 1 column 1 (char 0) (Python)&lt;br&gt;
Python's equivalent of the &amp;lt; and empty-string cases. The content isn't JSON at all — it's HTML, it's empty, or it's a plain-text error. Print the first 200 characters of the raw response.&lt;/p&gt;

&lt;p&gt;Extra data: line 2 column 1 (char N) (Python)&lt;br&gt;
This one gets misdiagnosed constantly. Your file looks like this:&lt;/p&gt;

&lt;p&gt;{"id": 1, "status": "shipped"}&lt;br&gt;
{"id": 2, "status": "pending"}&lt;br&gt;
That file is not broken. It's JSONL (also called NDJSON) — one JSON document per line, which is what log shippers, BigQuery exports and streaming APIs emit, because it appends without rewriting and streams without buffering.&lt;/p&gt;

&lt;p&gt;It is not one JSON document, so a whole-document parser reads line 1 successfully, finds more content, and complains. Parse it line by line:&lt;/p&gt;

&lt;p&gt;with open("data.jsonl") as f:&lt;br&gt;
    rows = [json.loads(line) for line in f if line.strip()]&lt;br&gt;
Or in pandas: pd.read_json("data.jsonl", lines=True).&lt;/p&gt;

&lt;p&gt;Bad control character in string literal&lt;br&gt;
A raw newline or tab inside a string. JSON strings can't contain literal control characters — they must be escaped as \n, \t, \r.&lt;/p&gt;

&lt;p&gt;This is what happens when someone builds JSON with string concatenation and interpolates a multi-line value. Which is the actual lesson: don't build JSON by hand. JSON.stringify and json.dumps exist and they escape correctly.&lt;/p&gt;

&lt;p&gt;Invalid \escape&lt;br&gt;
A lone backslash. The classic is a Windows path:&lt;/p&gt;

&lt;p&gt;{"path": "C:\Users\ada"}&lt;br&gt;
\U isn't a valid escape sequence. JSON knows \", \, \/, \b, \f, \n, \r, \t, and \uXXXX. Everything else is an error. The fix is C:\Users\ada.&lt;/p&gt;

&lt;p&gt;No error at all — and that's the bug&lt;br&gt;
{"id": 1, "id": 2}&lt;br&gt;
Duplicate keys. This parses. The spec says the behaviour is undefined; in practice almost every parser silently keeps the last value and discards the first.&lt;/p&gt;

&lt;p&gt;So it never throws, you never see a warning, and a field just quietly has the wrong value. This is the worst one on the list precisely because it isn't an error.&lt;/p&gt;

&lt;p&gt;The three-step debug&lt;br&gt;
Look backwards from the reported position, not at it. The parser blames the character where it gave up.&lt;br&gt;
Print the raw string before parsing. Half of all "JSON errors" are HTML error pages, empty bodies, or already-parsed objects. Neither is a JSON problem.&lt;br&gt;
Then use a validator that gives you line and column rather than a byte offset, because counting to character 4,721 by hand is not a debugging strategy.&lt;br&gt;
For step 3 I use a JSON validator that points at the exact line. It runs in the browser, which matters more than it sounds — the JSON you're debugging is by definition the real payload, usually with a token or a customer record in it, and pasting that into a server-side tool is how it ends up somewhere you didn't intend. (Some of those tools have share links that default to public. Check before you paste.)&lt;/p&gt;

&lt;p&gt;If the JSON is broken in the mechanical ways above rather than genuinely malformed — fences, trailing commas, True/None, single quotes — &lt;a href="https://mergejsonfiles.com/json-repair" rel="noopener noreferrer"&gt;https://mergejsonfiles.com/json-repair&lt;/a&gt; fixes those and shows a log of what it changed. The log matters for the truncation case: you want to know when "fixed" meant "closed the brackets around incomplete data".&lt;/p&gt;

&lt;p&gt;And when the document is valid but unreadable, a formatter is the fastest validator you have anyway. If it won't format, it won't parse.&lt;/p&gt;

&lt;p&gt;The short version&lt;br&gt;
Message Real cause&lt;br&gt;
Unexpected token }  Trailing comma&lt;br&gt;
Unexpected end of JSON input    Unclosed bracket, or truncated/empty data&lt;br&gt;
Unexpected token '  Single quotes&lt;br&gt;
Unexpected token o at position 1    You parsed an object, not a string&lt;br&gt;
Unexpected token &amp;lt;  It's an HTML error page&lt;br&gt;
Unexpected token n / T  NaN/None/True — Python leaked in&lt;br&gt;
Expecting property name...  Trailing comma or unquoted key&lt;br&gt;
Expecting value: line 1 column 1    Not JSON at all — check the raw response&lt;br&gt;
Extra data: line 2  It's JSONL, parse line by line&lt;br&gt;
Bad control character   Literal newline in a string&lt;br&gt;
Invalid \escape Unescaped Windows path&lt;br&gt;
(no error)  Duplicate keys — last one silently wins&lt;br&gt;
What's the worst JSON error message you've had to decode? The &amp;lt;!DOCTYPE one got me for a solid twenty minutes once.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>debugging</category>
      <category>programming</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
