ValueError: Trailing data

Quick answer

The input holds more than one JSON document — almost always NDJSON / JSON Lines (one object per line). json.loads and pandas.read_json each expect a single value. Fix it with pd.read_json(path, lines=True), or parse each line yourself. (The json module's wording for the same thing is JSONDecodeError: Extra data.)

The exact error string

import pandas as pd

# events.jsonl  (one JSON object per line)
# {"id": 1, "type": "click"}
# {"id": 2, "type": "view"}

pd.read_json("events.jsonl")
# ValueError: Trailing data

pandas parsed the first object, then found a second one on the next line. Because it was told to expect a single JSON document, the leftover is "trailing data." The file is JSON Lines, not one JSON value.

Why this happens

A JSON document is exactly one value — one object, one array. NDJSON files stack many objects, one per line, with no wrapping array. A standard parser reads the first value greedily and then expects only whitespace; the next object is unexpected, so it reports trailing data. This is the Python sibling of JavaScript's Unexpected non-whitespace character after JSON data.

JSON document versus NDJSON A single JSON document parses cleanly, while NDJSON contains multiple documents and needs lines=True. JSON { "id": 1 } ✓ One document json.loads() / read_json() work NDJSON · JSON Lines {"id": 1} {"id": 2} {"id": 3} Multiple documents needs lines=True
One JSON value parses directly; stacked objects (NDJSON) are many values — read them with lines=True or one line at a time.

Fix 1: pandas — read it as JSON Lines

Tell pandas the file is line-delimited with lines=True; each line becomes a row:

df = pd.read_json("events.jsonl", lines=True)   # ✅ one row per line

# huge file? stream it in chunks:
reader = pd.read_json("events.jsonl", lines=True, chunksize=10_000)
for chunk in reader:
    process(chunk)

Fix 2: json — parse one line at a time

json.loads decodes a single document, so split the text and parse each non-empty line:

import json

with open("events.jsonl") as f:
    rows = [json.loads(line) for line in f if line.strip()]

# rows is now a list of dicts

Fix 3: it was supposed to be one document

If the data is not meant to be NDJSON, then something appended extra content — a doubled payload, a stray brace, or non-JSON text. Inspect the raw text and fix the source that produced two values where one belongs:

raw = open("data.json").read()
print(repr(raw[-80:]))            # look at the tail for the leftover

# a real single document should parse cleanly:
data = json.loads(raw)            # fix the producer if this still raises

To see exactly where the second value starts, paste the body into the JSON Validator — it flags the first point that isn't part of one valid document.

Debugging checklist

Frequently Asked Questions

What does 'ValueError: Trailing data' mean?

It means the parser read one complete JSON document and then found more data after it. Both json.loads and pandas.read_json expect a single JSON value, so a file with multiple objects — one per line (NDJSON) — triggers 'Trailing data' on the second object.

How do I fix it in pandas.read_json?

Pass lines=True: pd.read_json(path, lines=True). That tells pandas the file is JSON Lines (one JSON object per line) rather than a single JSON document, and it reads each line into a row. Without lines=True, pandas tries to parse the whole file as one value and fails on the second line.

How do I fix it with json.loads?

json.loads parses exactly one document. For NDJSON, split on newlines and parse each non-empty line: [json.loads(line) for line in text.splitlines() if line.strip()]. If the file is meant to be a single array, fix the producer to emit a JSON array instead of stacked objects.

What is NDJSON / JSON Lines?

NDJSON (newline-delimited JSON), also called JSON Lines or .jsonl, stores one JSON object per line with no enclosing array. Log pipelines, data exports, and streaming APIs use it because each line can be written and read independently. It is not a single JSON document, so a normal parser rejects it.

How is this different from JSONDecodeError: Extra data?

They are the same underlying problem — more than one JSON value in the input. json.loads raises json.decoder.JSONDecodeError: Extra data; pandas.read_json surfaces it as ValueError: Trailing data. The fixes are identical: treat the input as JSON Lines or parse one document at a time.

Could a stray character or BOM cause it?

Yes. If a single JSON document has trailing junk — an extra brace, a duplicated payload, or non-JSON text appended — the parser finishes the value and then hits the leftover, reporting trailing data. Inspect the raw text and trim the extra content, or fix whatever appended it.

Find where the extra data starts

Paste the body into the validator to see the first point that isn't part of one valid JSON document — nothing is uploaded to a server.

JSON Validator JSON Formatter All Error References
About the author

Pasindu Ishan is a software developer based in Sri Lanka. He builds privacy-first developer tools at JSON Dev Tools.