All tools run in your browser — your files never leave your device.
All tools154

Developer & Security

Three things that fail quietly and waste an afternoon

Three specific failures that produce no useful error message, and one of them can be introduced by your build tooling after the code was correct.

The short answer. JSON forbids trailing commas, comments and single-quoted strings, which is why hand-edited files fail to parse. Inside CSS calc(), whitespace around the plus and minus operators is required by the grammar — a minifier that strips it produces a declaration browsers discard silently. Regex lookbehind is now supported in every major browser, having been unavailable in Safari until 2023.

What JSON does not allow

JSON is a much smaller format than it appears, and nearly every parse failure in a hand-edited file is one of five things it forbids.

The specification is deliberately minimal, and JavaScript object literal syntax is considerably more permissive — which is exactly why people write invalid JSON without noticing.

  • Trailing commas. Valid in JavaScript, invalid in JSON. The commonest cause by a wide margin.
  • Comments. No // and no /* */. There is no comment syntax at all.
  • Single-quoted strings. Double quotes only, on both keys and values.
  • Unquoted keys. Every key is a quoted string.
  • NaN, Infinity and undefined. Not JSON values. Use null.

Duplicate keys are the odd case: technically permitted by the specification but with undefined behaviour, so parsers differ. Most take the last occurrence. Relying on that is a bug waiting to be discovered on a different runtime.

Reading the error

Parse errors report a position, and the position is where the parser gave up rather than where the mistake is. A missing comma on line 40 is often reported at line 41.

Formatting the document first is the fastest route to the cause, because a validator that pretty-prints shows the structure and highlights the failure in context.

Two other causes worth knowing when the content looks correct. A byte order mark at the start of a UTF-8 file makes some parsers reject the first character — invisible in most editors, and immediately visible in a hex view. And a file that is actually JSON Lines, one object per line with no enclosing array, is valid as a format and invalid as a single JSON document. JSON Formatter runs locally, which matters when the JSON is an API response containing customer records.

The calc() whitespace rule

This one is a genuine trap because the code is correct when written and broken after the build.

The CSS grammar requires whitespace around the + and - operators inside calc(). Not as a style convention — as a parsing requirement. calc(100% - 20px) is valid; calc(100%-20px) is not.

The calc() whitespace rule
WrittenValid?Why
calc(100% - 20px)YesSpaces around the operator
calc(100%-20px)NoAmbiguous with a signed number
calc(100%/3)Yes* and / do not need spaces
calc(100% -20px)No-20px parses as a signed value
calc(var(--a) + 1px)YesSpaces present

The reason is ambiguity: -20px is itself a valid signed length, so without the space the parser cannot tell subtraction from a negative number. The consequence is what makes it nasty — an invalid declaration is not an error you see. Browsers discard declarations they cannot parse, so the rule silently does not apply and the layout is wrong with nothing in the console.

Why a minifier causes it

Minifiers remove whitespace, and a naive one removes it everywhere. Modern minifiers know about calc and leave those spaces alone; older tools, hand-rolled regex-based minifiers and some template pipelines do not.

The failure appears only in the built output, which is why it survives review — the source is correct, and nobody reads the minified file.

  1. Search the built CSS for calc( and check the operators still have spaces around them.
  2. Use a current minifier. The well-maintained ones handle this correctly.
  3. Add a build check that fails on a calc without whitespace — this is cheap and permanent.
  4. Watch CSS variables inside calc, where a variable holding a negative value creates the same ambiguity at runtime.

A build check is the right answer because the failure is invisible by construction. This site runs one for exactly this reason: a deploy gate that fails on a calc missing its whitespace catches the problem before it reaches anyone. Code Minifier preserves the required spacing.

Lookahead and lookbehind

Lookarounds match a position rather than consuming characters, which is what makes them useful and what makes them confusing.

A lookahead asserts what follows without including it in the match. A lookbehind asserts what precedes it. Neither appears in the matched text.

  • (?=…) positive lookahead — followed by this.
  • (?!…) negative lookahead — not followed by this.
  • (?<=…) positive lookbehind — preceded by this.
  • (?<!…) negative lookbehind — not preceded by this.

The practical example is matching a price without capturing the currency symbol: (?<=£)\d+(?:\.\d{2})? matches the number and leaves the symbol out of the result. Doing the same with a capture group works too, and then you have to remember to read group 1 instead of the whole match.

Support, and where it still bites

Lookbehind was the long-standing gap. JavaScript gained it in ES2018, but Safari did not ship it until version 16.4 in March 2023 — so for five years it was unusable in code that had to run everywhere, and a great deal of advice still warns against it on those grounds.

It is now supported in every current browser. The remaining caution is that older Safari versions throw a syntax error when the pattern is parsed, which can take down a whole script rather than failing one match.

Elsewhere the picture differs. Python, .NET, Java and PCRE have had lookbehind for years, though several require it to be fixed-width — variable-length lookbehind is a JavaScript and .NET capability, not a universal one. Test the pattern against real input rather than assuming; Regex Tester runs it in the browser with the match positions shown.

Frequently asked questions

Why does my JSON fail to parse?

Usually a trailing comma, which is valid in JavaScript and invalid in JSON. The other frequent causes are comments, single-quoted strings, unquoted keys, and NaN or Infinity as values.

Can JSON have comments?

No — there is no comment syntax in the format at all. JSON5 and JSONC add them, but they are different formats and a standard JSON parser rejects both.

Why is the reported error line wrong?

The position reported is where the parser gave up, not where the mistake is, so a missing comma on line 40 often reports at line 41. Format the document first to see the structure in context.

Why did minifying my CSS break the layout?

Probably a calc() expression. CSS requires whitespace around + and - inside calc, because -20px is itself a valid signed length and the parser cannot otherwise tell subtraction from a negative number. A minifier that strips those spaces produces a declaration browsers discard silently.

How do I catch the calc() problem?

Add a build check that fails when a calc contains an operator without surrounding whitespace. The failure produces no console error and appears only in built output, so a check is the only reliable defence.

What is the difference between lookahead and lookbehind?

Lookahead asserts what follows the current position; lookbehind asserts what precedes it. Neither consumes characters, so neither appears in the matched text — which is what makes them useful for matching a value without its surrounding markers.

Is regex lookbehind safe to use now?

In browsers, yes — Safari shipped it in 16.4 in March 2023 and every current browser supports it. Older Safari throws a syntax error when the pattern is parsed, which can break an entire script rather than one match. Some other languages still require fixed-width lookbehind.

Stop reading, start doing

Every tool in this guide is free.

154 browser-based utilities. No account, no upload, and no file size limit — your files are processed on your own device and never sent anywhere.

Browse all 154 tools