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.
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
- ✓ One JSON object per line? It's NDJSON — use
read_json(..., lines=True) - ✓ Using
json.loads? Split on newlines and parse each line - ✓ Huge file? Stream with
chunksize=(pandas) or iterate the file object - ✓ Supposed to be one document? Inspect the tail and fix the producer
- ✓ Same error from
json.loadsis JSONDecodeError: Extra data — identical cause - ✓ Locate the leftover with the JSON Validator
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.