English

Developer tools · JSON formatter & validator

Why a JSON Lines file fails validation at line 2, column 1

· How it works

json developer-workflow validation

Why a JSON Lines file fails validation at line 2, column 1 illustrated with JSON tokens and a precise validation boundary
Original ToolAcre vector illustration

A .jsonl file is many JSON documents, not one, so a strict validator stops exactly where the second one begins. This post explains the JSON Lines and NDJSON conventions and how to validate them one record at a time.

Valid on every line, invalid as a file

Valid on every line, invalid as a file — the export that every downstream tool reads happily but a validator rejects at the second line. A log shipper can consume each newline as a record boundary, yet a strict JSON parser sees the whole file as one input. The first object is complete JSON; the next opening brace is an illegal second root value.

ToolAcre validates one JSON text, not JSON Lines. Once the scanner completes the first root value, any later non-whitespace character is reported as unexpected after the end of the JSON value. It does not offer per-line NDJSON validation or conversion as a hidden fallback. That distinction prevents a green result from implying that every record in a line-oriented stream was checked.

One text, one value — what RFC 8259 defines as a JSON text and why two top-level values in a row are a grammar error

One text, one value — what RFC 8259 defines as a JSON text and why two top-level values in a row are a grammar error. A JSON text is a serialized value, so an object, array, string, number, boolean or null can stand at the root. Whitespace may surround that value, but it cannot separate several roots into a larger valid document.

For example, `{"ok":true} {"ok":false}` contains two individually valid objects but is not one JSON text. Parsing the first object consumes a complete value; parsing the entire string must then reject the second `{`. To represent both values in ordinary JSON, place them inside an array and add the comma required between array elements.

JSON Lines and NDJSON

JSON Lines and NDJSON — the newline-delimited conventions, why they exist for streaming and logs, and how they differ from a JSON array. Each physical line carries one complete JSON value, normally an object, and the newline acts as framing outside JSON grammar. Producers can append records and consumers can process them incrementally without loading a complete collection.

An array instead has one opening bracket, comma-separated elements and one closing bracket, making the whole file a single JSON value. It is convenient for APIs that return a bounded collection but awkward for an indefinitely growing event stream. A truncated JSON Lines file may preserve all complete earlier records; a truncated array commonly leaves the enclosing value unfinished.

Why the error is always at line 2, column 1

Why the error is always at line 2, column 1 — the parser finishes the first value, expects end of input, and meets the first character of the second record. The newline itself is legal trailing whitespace, so it does not trigger the failure. The next record’s opening brace is the first token that contradicts the completed-document state.

That location is diagnostic evidence rather than a claim that the second object is malformed. If the report consistently points to the first non-whitespace character after a valid root, inspect the file shape before editing punctuation. Deleting the brace would corrupt the record; choosing a line-aware reader or converting the records into an array addresses the actual framing mismatch.

Worked example: validating three log records

Worked example: validating three log records — checking each line on its own versus wrapping them in an array with commas. Suppose the lines contain `{"level":"info"}`, `{"level":"warn"}` and `{"level":"error"}`. A line-oriented validator parses three separate inputs and can identify the exact record if one has a missing quote or trailing comma.

For a strict whole-document check, transform the sample to `[{"level":"info"},{"level":"warn"},{"level":"error"}]`. The brackets establish one root and the commas delimit its elements. Do not merely replace newlines with commas: that produces three roots separated by punctuation unless the surrounding array is added, and it can mishandle blank lines that the source convention may forbid or ignore.

Converting between the two shapes

Converting between the two shapes — when a wrapping array is appropriate and when it would defeat the point of line-delimited output. A finite export intended for an API request, editor or strict validator can often become an array. Conversion must parse every record first, because textual concatenation cannot safely account for embedded escaped characters or invalid lines.

Keep JSON Lines when records arrive continuously, files are appended, or consumers need bounded memory and record-level recovery. Converting a multi-gigabyte event stream into one array requires retaining container state and delays a complete parse until the closing bracket arrives. In the other direction, serialize each array element compactly on one line and define whether empty lines or final newlines are permitted.

What this does not cover

What this does not cover — concatenated JSON without newlines and record-separator framing (RFC 7464), which need dedicated parsers. Values placed directly together cannot be split safely with a simple line operation, especially when roots may be numbers or strings. RFC 7464 uses an ASCII record-separator character to frame JSON text sequences rather than relying only on visible newlines.

It also does not validate application rules shared by records. Parsing every line cannot prove timestamps are ordered, identifiers are unique or all objects use the same schema. Those checks belong after record framing and syntax parsing. Likewise, a newline embedded as the escape sequence ` ` inside a string is data, not a physical boundary, and a compliant line reader must preserve that distinction.

Takeaway: know which shape you are holding

Takeaway: know which shape you are holding — and how the validator's position tells you instantly that a file is line-delimited. A failure at the first token of line two after a complete line-one value strongly indicates multiple framed records, not broken syntax in the first record. Check the extension, producer documentation and expected consumer before changing the data.

Use a JSON Lines or NDJSON parser to validate records independently when the newline is intentional. Use an array when the destination requires one complete JSON collection. ToolAcre correctly rejects the multi-root file because its contract is strict single-text validation; the rejection protects that contract rather than showing that newline-delimited JSON is inherently defective. Match the validator to the framing format.