You open the file, scan it, and everything looks fine. The braces match, the indentation is tidy, and every key has a value. Then the parser throws something like "Unexpected token } in JSON at position 142" and the build stops. It feels unfair, because the file reads perfectly well to a person.
The gap is that people read JSON loosely and parsers read it strictly. A human fills in the intent, forgives a stray comma, and ignores a character that looks like a quote mark. A parser does none of that, and the error it prints often points at the wrong place. This guide walks through the mistakes that hide best and a repeatable way to find the real one fast.
JSON Is Stricter Than It Looks
JSON looks like a JavaScript object, and that resemblance causes most of the trouble. The format is defined by RFC 8259, and its grammar is much smaller and less forgiving than the language it was borrowed from. The official summary at json.org fits on one page, which is a good sign of how little the format allows.
Keys must be strings in double quotes. Strings must use double quotes too. There is no comment syntax, no trailing comma, no undefined, no NaN, and no way to write a number with a leading plus sign. Anything outside that list is simply not JSON, even if it works fine in a script or an editor that is lenient about it.
Most hand-edited files fail because the author wrote something that would be legal in a nearby format. Configuration files for tools often use looser dialects, so habits carry over. The parser in your application does not know which dialect you meant, so it applies the strict rules to every byte.
Photo by Boris Hamer on Pexels
The Trailing Comma and Why the Error Lands on the Wrong Line
The single most common cause is a comma after the last item in an object or array. It is easy to create. You add a new field at the bottom, or you delete the last entry and forget the comma that used to separate it from the one before.
What makes it frustrating is where the error shows up. The parser reads the comma, expects another value, and only discovers the problem when it reaches the closing brace. The message points at the brace, not the comma, so you stare at the wrong character. Some runtimes report a position in characters rather than a line, which is hard to use in a long file.
A useful habit is to read the error location as "the problem is at or just before this point." When the position lands on a closing bracket, check the line above it first. A trailing comma is the cause far more often than anything wrong with the bracket itself.
Single Quotes, Smart Quotes, and Unquoted Keys
Single quotes are the second classic. A snippet copied from a Python dictionary or a JavaScript object literal often uses them, and JSON rejects every one. The same goes for unquoted keys such as name: "report", which are fine in a script and invalid in JSON.
Smart quotes are the sneakier version. If the text passed through a word processor, a chat window, or a web page that styles punctuation, the straight quote marks may have been swapped for curly ones. They look nearly identical in many fonts, which is why the file seems fine and still fails. The parser sees an unexpected character and stops.
The fix is to search for the curly forms directly rather than trusting your eyes. Most editors can highlight non-ASCII characters, and the Visual Studio Code editor flags unusual Unicode characters by default so they stand out. If you paste configuration from documentation or an email, assume it may have been restyled along the way.
Comments Are Not Allowed
People want to leave notes in configuration files, so they add // or /* */ comments. Standard JSON does not support either one. A parser that follows the specification treats the first slash as an error.
This causes confusion because some tools do accept comments. Editor settings files and TypeScript project files use a relaxed variant often called JSON with comments, and the TypeScript compiler reads its configuration that way. A file that works there can fail the moment you feed it to a strict parser in a different program.
If you need explanatory text in data that a strict parser will read, put it in a real field, such as a key named _note or description. It is less elegant than a comment, but it survives every parser and keeps the file portable.
Invisible Characters: BOMs, Non-Breaking Spaces, and Raw Tabs
Some of the hardest failures come from characters you cannot see. A byte order mark at the start of a file is the best known. Some Windows tools add one when saving UTF-8 text, and many parsers reject it with an error that mentions an unexpected token at position zero, which looks absurd on a file that starts with a clean opening brace.
Non-breaking spaces are the next offender. JSON allows only four whitespace characters: space, tab, line feed, and carriage return. A non-breaking space pasted in from a web page or a document looks exactly like a normal space, but a strict parser treats it as garbage outside of a string.
Raw control characters inside strings cause a related failure. A literal tab or line break in the middle of a string value must be written as an escape sequence such as \t or \n. If a multi-line value was pasted in as is, the file is invalid even though each line looks reasonable.
Photo by Feyza Daştan on Pexels
Numbers and Values That Quietly Change Meaning
Not every JSON problem is a parse error. Some files parse cleanly and then mean something different from what you intended. Numbers are the main example. Many parsers read JSON numbers into floating point values, so an integer larger than about nine quadrillion can lose its last digits without any warning. Identifiers that are long numbers are safer as strings for this reason.
Leading zeros are rejected by the grammar, so 007 is invalid, and values like NaN or Infinity that come out of some serializers are not legal either. If a data export contains them, the file will fail in a strict consumer even though it was produced by working software.
Duplicate keys are another quiet trap. The specification says names should be unique but does not forbid repeats, and parsers disagree about what to do. Many keep the last value, some keep the first, and some raise an error. A file with two timeout entries can behave differently depending on which program reads it.
"Most JSON bugs that reach a code review were visible the whole time. The file was never validated by anything stricter than a human glance, and a glance is exactly the thing that skips a trailing comma." - Dennis Traina, founder of 137Foundry
A Repeatable Way to Find the Real Error
Guessing is slow, so use a fixed routine. First, paste the content into a validator rather than into your application, so you get a precise location without a build or a restart. A good JSON formatter and validator highlights the failing line and character and then re-indents the rest, so structural mistakes become visible.
Second, read one line before the reported position. As noted earlier, the error is usually raised after the parser has already gone wrong, so the real defect sits just behind it. Third, check the three usual suspects in order: trailing commas, quote characters, and anything pasted from outside the editor.
Fourth, if the position is at the very start, suspect a byte order mark or hidden whitespace and re-save the file as plain UTF-8 without a signature. Finally, when a large file will not yield, cut it in half and validate each half separately. Narrowing by halves finds a single bad character in a few rounds, even in a file with thousands of lines.
Photo by Brett Sayles on Pexels
Stop the Problem Before It Ships
Finding an error once is fine. Finding the same one every month is a process problem. The cheapest prevention is to stop hand-editing files that a machine can generate. If a program writes the JSON, the serializer handles quoting, escaping, and commas correctly every time.
When a file must be edited by hand, add a validation step to the workflow. A pre-commit check or a short script using the parser built into Node.js or Python can reject a bad file before it reaches a branch. Both ship with a strict JSON parser, so the check costs almost nothing to add.
For command line work, the jq tool is a good companion. Running a file through it prints a clear error and refuses to continue on invalid input, which makes it a handy gate in scripts. Pairing it with a consistent formatter also keeps diffs small, because every change shows up as a real change instead of a whitespace shuffle.
Where a Validator Fits in Everyday Work
None of this requires memorizing the grammar. It requires a quick way to ask a strict reader what it thinks of your file before your application does. Keeping a validator open in a browser tab takes seconds and saves the longer loop of rebuilding and rereading logs.
The JSON Formatter & Validator on EvvyTools formats, validates, and explores JSON with instant error detection, so a pasted blob either comes back clean and indented or points straight at the problem. It is useful for API responses, configuration files, and any data you were handed rather than generated yourself.
You can browse more utilities in the EvvyTools tools directory, read related walkthroughs on the EvvyTools blog, or start from the EvvyTools homepage to see the full catalog. The next time a file looks perfect and still fails, remember that the parser is not wrong. It is just reading every character, and your eyes are not.