json.decoder.JSONDecodeError: Extra Data (tested)
json.loads() expects the entire string to be exactly one JSON value. The moment anything else follows — a second object, a trailing comment, a newline-delimited second line — it raises json.decoder.JSONDecodeError: Extra data. We measured exactly where it stops and how to parse past it.
1. The error, with two JSON objects back to back
import json
json.loads('{"a": 1}{"b": 2}')
json.decoder.JSONDecodeError: Extra data: line 1 column 9 (char 8)
Measured: json.loads() parsed the first complete object, {"a": 1} (8 characters), successfully — then found the second { starting at character 8 and raised, because a valid JSON document is supposed to end there. The position it reports is exactly where the first valid value ended, not where anything is actually malformed.
2. The most common real trigger: a JSON Lines file
json.loads('{"a": 1}\n{"b": 2}\n')
json.decoder.JSONDecodeError: Extra data: line 2 column 1 (char 9)
json.loads('{"a": 1} // comment')
json.decoder.JSONDecodeError: Extra data: line 1 column 10 (char 9)
Measured: a newline-delimited JSON Lines (.jsonl) file produces this exact error if you call json.loads() on the whole file — Python's json module has no built-in JSON Lines support. The same error also fires for a trailing // comment, since JSON has no comment syntax at all; json.loads() stops at the first complete value and anything after is "extra" regardless of what it looks like.
3. This is a different error from a trailing comma
json.loads('{"a": 1,}')
json.decoder.JSONDecodeError: Illegal trailing comma before end of object: line 1 column 8 (char 7)
Measured: a trailing comma inside the same object raises a distinctly worded error, not "Extra data" — useful for telling the two apart from the message alone: "Extra data" means the document doesn't end where it should; "Illegal trailing comma" means punctuation inside one value is wrong.
4. The fix: parse one value at a time with raw_decode()
def parse_concatenated(s):
dec = json.JSONDecoder()
results = []
idx = 0
s = s.strip()
while idx < len(s):
obj, end = dec.raw_decode(s, idx)
results.append(obj)
idx = end
while idx < len(s) and s[idx].isspace():
idx += 1
return results
parse_concatenated('{"a": 1} {"b": 2} {"c": 3}')
[{'a': 1}, {'b': 2}, {'c': 3}]
Measured: JSONDecoder().raw_decode(s, idx) parses exactly one JSON value starting at idx and returns (value, end_index) instead of raising on whatever comes after — it's the building block both json.loads() uses internally and what you need to pull multiple back-to-back values out of one string.
5. For an actual JSON Lines file, split first
lines = open("data.jsonl").read().splitlines()
records = [json.loads(line) for line in lines if line.strip()]
Measured: for a real .jsonl file (one JSON value per line, which is the common wire format for streaming APIs and log files), splitting on newlines first and calling json.loads() per line is simpler than raw_decode() and handles blank lines correctly with the if line.strip() guard. Use raw_decode() instead when values are concatenated without a reliable line-based separator.
6. How to tell what you're actually looking at
If json.loads() raises "Extra data" and e.pos lands right after what looks like one complete object, you don't have a single JSON document — you have several, either concatenated or one per line. Check the source: an API that streams multiple objects per response, or a log/export file, is almost always JSON Lines. Fix the parsing strategy (split-and-loads, or raw_decode() in a loop) rather than trying to make json.loads() accept it directly — it never will, by design.
Frequently asked questions
What does "Extra data" actually mean in a JSONDecodeError?
We confirmed it means json.loads() successfully parsed one complete JSON value and then found more content after it — the position reported (e.pos) is where that first value ended, not where anything is malformed.
Why do I get "Extra data" when loading a .jsonl (JSON Lines) file?
Because we measured that Python's json module has no built-in support for JSON Lines — calling json.loads() on a whole multi-line file parses only the first line's object, then raises Extra data at the start of line 2.
How is "Extra data" different from "Illegal trailing comma"?
We confirmed these are two distinctly worded errors: Extra data means the document doesn't end where a complete JSON value ends, while Illegal trailing comma means punctuation inside one value (like {"a": 1,}) is itself invalid — the wording alone tells you which problem you have.
What's the fix for parsing multiple concatenated JSON objects in one string?
We tested json.JSONDecoder().raw_decode(s, idx), which parses exactly one value starting at a given index and returns where it ended — looping it with that end index lets you pull out every value without json.loads() raising on what follows.
What's the simplest way to parse an actual JSON Lines file?
We'd split on newlines first and call json.loads() on each non-blank line individually — simpler than raw_decode() and the standard approach for the common one-object-per-line wire format used by streaming APIs and log exports.
Written with AI assistance. Measured on 2026-10-03 with Python 3.13.5's built-in json module, calling json.loads() and json.JSONDecoder().raw_decode() directly and printing the exact exception text. Every message below is copy-pasted output, not paraphrased. PlainHeaders is our extension; Python's json module is built in.