Fixing JSON6 Parse Errors
How to diagnose and fix the errors the json-6 parser throws, and the mistakes it lets through.
TL;DR: Read the [line:col] at the end of the message, then look at the character before it: a missing comma is reported at the next key. Unclosed braces say "No value found in document", and text after the first value is silently ignored.
Reading a JSON6 Error Message
A JSON6 parse error tells you what the parser was doing, which character stopped it, and where. The shape is always the same:
fault parsing 'b' unexpected at 6 (near ':1 [b]:2}') [1:6] The character in square brackets inside near is the first one the parser could not accept, and [1:6] is its one-based line and column. Two details trip people up. First, the errors are plain Error objects, not SyntaxError, so a catch that filters on instanceof SyntaxError will miss them. Second, the position is the first character that is wrong, which is frequently the token after the real mistake: a missing comma is reported at the start of the next key.
The full list of messages, each with a live example, is in the error reference. This page covers the mistakes that cause most of them.
The Most Common Mistakes
Every message below was produced by running the "wrong" snippet through JSON6.parse() from json-6 1.1.7.
Missing comma between members
Wrong
{ name: 'app' version: '1.0' }Correct
{ name: 'app', version: '1.0', }fault parsing 'v' unexpected at 19 (near '\n [v]ersion: '1') [3:3] The parser reaches version, finds a key where it expected a comma, and stops. The same mistake in an array of numbers or booleans produces "Two values with no separator between them" instead. Newlines are whitespace in JSON6, so a line break never substitutes for a comma.
Unclosed brace or bracket
Wrong
{ server: { port: 8080, }, log: { level: 'info' },Correct
{ server: { port: 8080, }, log: { level: 'info' }, }No value found in document This is the least helpful message in the library. An unclosed { or [ does not report a position; it reports that the whole document held no value. If you see it, the fix is nearly always at the end of the file, and a bracket-matching editor finds the unmatched opener in seconds.
Unclosed string
Wrong
{ message: 'Hello world, port: 8080, }Correct
{ message: 'Hello world', port: 8080, }Incomplete string at 42 [4:1] JSON6 strings can span lines, so a missing closing quote does not end at the line break the way a JSON string does. It swallows everything to the end of the file, and the error is reported there. Search backwards for a quote with no partner, and watch for apostrophes inside single-quoted strings: 'don't' needs the inner quote escaped, or a different outer quote.
Unquoted string value
Wrong
{ mode: production, }Correct
{ mode: 'production', }fault parsing 'p' unexpected at 11 (near 'e: [p]roduction,') [2:9] Keys may be bare words; values may not, except true, false, null, undefined, NaN and Infinity. Writing a bare word as a value is a common habit carried over from YAML.
Semicolon instead of comma
Wrong
{ port: 8080; host: 'localhost' }Correct
{ port: 8080, host: 'localhost' }fault while parsing number; ';' unexpected at 13 (near '080[;] host: 'lo') [1:13] The semicolon is rejected by the number parser, since it is the first character that cannot continue 8080.
Hash comments
Wrong
# server settings { port: 8080 }Correct
// server settings { port: 8080 }fault parsing '#' unexpected at 1 (near '[#] server se') [1:1] Only // and /* */ are comments. There is no # comment, even though the library's own README lists it as a "todo".
Space or quote in a bare key
Wrong
{ my key: 1 }Correct
{ 'my key': 1 }fault while parsing; character unexpected 'k' unexpected at 6 (near 'my [k]ey: 1 }') [1:6] A bare key ends at whitespace, so the parser sees my and then a second word. Hyphens and dots are fine in bare keys (content-type: 1 is legal) unless you enable esStrictCompatible.
Number with trailing characters
Wrong
{ id: 12abc, ratio: 1.2.3 }Correct
{ id: '12abc', ratio: 1.23 }fault while parsing number; 'a' unexpected at 9 (near ' 12[a]bc, ratio:') [1:9] A number token ends at the first character that cannot belong to it. Version strings such as 1.2.3 are not numbers and must be quoted, and so must identifiers that merely start with digits. Only the first problem is reported, so a file can fail again after you fix it.
Backslashes in Windows paths
Wrong
{ dir: 'C:\users\me' }Correct
{ dir: 'C:\\users\\me' }(escaped character, parsing hex of \u) 's' unexpected at 13 (near ':\u[s]ers\me' }') [1:13] A backslash starts an escape sequence, and \u must be followed by hex digits. \users therefore fails inside the escape, which is the lucky outcome: 'C:\temp\new' parses without complaint and silently contains a tab and a newline. Double every backslash, or use forward slashes, which Windows accepts.
Key with no value
Wrong
{ port: , host: 'localhost' }Correct
{ port: 8080, host: 'localhost' }Unexpected comma after object field name ',' unexpected at 9 (near 't: [,] host: 'lo') [1:9] Also reported for { port } and { port: } with slightly different wording. JSON6 has no shorthand property syntax.
Problems That Do Not Raise an Error
The riskiest mistakes are the ones that parse. JSON6.parse() returns as soon as it has one complete value and ignores whatever follows. Native JSON.parse and JSON5 both reject trailing text; JSON6 does not.
const JSON6 = require('json-6'); // A stray closing brace ends the document early. Nothing throws. const config = JSON6.parse('{ a: 1 }, b: 2 }'); console.log(config); // Two values: only the first is returned. console.log(JSON6.parse('1 2'));{ a: 1 } 1 A stray extra } in the middle of a config file therefore truncates it quietly, and every setting after the stray brace disappears. The fix is to parse the text a second time, wrapped in an array with a sentinel after it. The wrapped parse succeeds as [value, sentinel] only when the text held exactly one complete value; trailing text, a second value, an extra bracket or an unclosed bracket all break the pattern:
const JSON6 = require('json-6'); // Wrap the text in an array with a sentinel after it. The result is // [value, 'end'] only if the text held exactly one complete value. function parseOne(text) { const value = JSON6.parse(text); // real syntax errors, with positions let check; try { check = JSON6.parse('[' + text + '\n,"end"]'); } catch (err) { throw new Error('text after the first value, or an unclosed bracket'); } if (check.length !== 2 || !(0 in check) || check[1] !== 'end') { throw new Error('expected exactly one value'); } return value; } for (const text of ['{ a: 1 }', '{ a: 1 }, b: 2 }', '{ a: 1', '{ a: 1 } {', '1 2']) { try { console.log(JSON.stringify(text), '->', parseOne(text)); } catch (err) { console.log(JSON.stringify(text), '-> ' + err.message); } }"{ a: 1 }" -> { a: 1 } "{ a: 1 }, b: 2 }" -> text after the first value, or an unclosed bracket "{ a: 1" -> No value found in document "{ a: 1 } {" -> text after the first value, or an unclosed bracket "1 2" -> text after the first value, or an unclosed bracket Prefer this pattern for anything loaded from disk. The config files tutorial builds it into a complete loader, including a guard against the __proto__ key, which JSON6.parse() treats as an instruction to change the prototype of the object it is building.
Debugging Techniques
Start with the position. A small helper turns the [line:col] suffix into a pointer at the offending character, which is faster than counting columns by hand:
function explain(text, err) { const at = /\[(\d+):(\d+)\]\s*$/.exec(err.message); if (!at) return err.message; // no position in this message const line = Number(at[1]); const col = Number(at[2]); const source = text.split(/\r\n|\r|\n/)[line - 1] || ''; const gutter = String(line) + ' | '; return [ err.message.replace(/\n/g, '\\n'), gutter + source, ' '.repeat(gutter.length + col - 1) + '^', ].join('\n'); } const text = `{ name: 'app' version: '1.0' }`; try { JSON6.parse(text); } catch (err) { console.log(explain(text, err)); }fault parsing 'v' unexpected at 19 (near '\n [v]ersion: '1') [3:3] 3 | version: '1.0' ^ The caret sits under version, so the problem is on the previous line: the comma after 'app' is missing. Beyond that:
- Bisect large files. Delete the bottom half and parse again. If it still fails, the problem is in the top half. Repeat until one line is left. This is the reliable way to find an unclosed container.
- Test with the strict options. Passing
{ esStrictCompatible: true }as the third argument toparse()turns on extra checks for leading-zero numbers, raw newlines in quoted strings and unusual keys. It is a cheap way to find text that parses but would mean something else in a JavaScript engine. - Paste into the validator. The online validator runs the same parser in your browser and shows the message beside the text.
- Check the encoding. A UTF-8 byte order mark at the start of the file is accepted, and so are non-breaking spaces and the form-feed and vertical-tab whitespace characters. Other control characters are reported as "fault parsing" with an invisible character between the quotes.
- Reduce to JSON. Remove every JSON6-specific feature and run
JSON.parse(). If that succeeds the mistake is in a feature you added, and the syntax reference tells you which rules apply.
Catching Errors Before Users Do
Parse errors in a hand-edited file are cheap to catch if you catch them early. Three habits cover most cases.
- Parse in CI. A one-line script that loads every
.json6file in the repository and fails the build on the first error finds a missing comma before it reaches a deploy. Use the single-value check from above so that truncated and over-long files fail too. - Fail loudly at startup. Load configuration once, when the process starts, and let an invalid file stop the process with the file name and line in the message. A service that discovers a bad setting an hour later, on first use, is much harder to diagnose.
- Write the file name into the error. The parser knows only the text it was given. Wrap the call and prefix the message with the path, as the loader in the config files tutorial does, so the error reads
production.json6:12:5instead of just[12:5].
A search of the npm registry on 10-27-2026 found no JSON6 linter or formatter, only json-6 itself and a few older or empty packages; the editors guide explains what editors can and cannot do with the .json6 extension. The practical workaround is the parser itself.
Using the Wrong Parser
When a JSON6 file is handed to JSON.parse the failure looks like this:
const text = "{ name: 'app', /* note */ port: 8080, }"; try { JSON.parse(text); } catch (err) { console.log(err.name + ': ' + err.message); }SyntaxError: Expected property name or '}' in JSON at position 2 (line 1 column 3) That message comes from Node itself, so its wording depends on the Node version. If the error says "in JSON at position", the file went through the built-in parser, not json-6. Check that the code path that loads the file calls JSON6.parse, that you are not using fetch(...).then(r => r.json()) on a .json6 URL (use r.text() and parse it yourself), and that a bundler or framework is not intercepting the import.
FAQ
Why does my JSON6 parse error point to the wrong line?
The parser reports the first character it cannot accept, which is usually the token after the actual mistake. For a missing comma it is the start of the next key, so check the end of the previous line. For an unclosed string it is the end of the file.
Why is my error not a SyntaxError?
json-6 throws new Error(...) for every parse failure, so err.name is "Error". Catch all errors around parse() and match on the message. The position is only available as text at the end of the message.
Why did a broken file load without an error?
JSON6.parse() returns after the first complete value and ignores the rest of the text. An extra closing brace, or two documents concatenated, parses as only the first one. Parse the text a second time inside an array with a sentinel, as shown above, to require exactly one value.
Are comments allowed in JSON6?
Yes, // line comments and /* */ block comments. A line comment may be the last thing in the file with no trailing newline. (The warnWithCommentWithoutEOL option exists, but in json-6 1.1.7 it only logs a warning when the text ends inside a line comment before any value is complete, which is already an error.)
Still Stuck?
Paste the document into the validator, or look up the exact message in the reference.