„Unexpected non-whitespace character after JSON at position …“ – Ursache und Lösung
„Unexpected non-whitespace character after JSON at position …“ heißt: Der Parser hat ein vollständiges, gültiges JSON-Dokument gelesen und danach noch etwas gefunden, das kein Leerraum ist. Ein JSON-Dokument besteht aber aus genau einem Wert. Alles dahinter ist ein Fehler, auch ein einzelnes Zeichen. Die Meldung zeigt dir den Anfang dieses Überschusses.
Am schnellsten siehst du die Stelle, wenn du den Text in den JSON-Formatierer einfügst. Er nennt Zeile und Spalte, erklärt den Fehler auf Deutsch und markiert die Stelle in der Eingabe, wenn du auf die Meldung klickst. Die Verarbeitung läuft komplett lokal im Browser, es wird nichts an einen Server gesendet.
Was die Meldung bedeutet
Nach RFC 8259 ist ein JSON-Text ein einzelner Wert (Objekt, Array, String, Zahl, true, false oder null), umgeben von optionalem Leerraum. Der Parser liest den ersten Wert bis zum Ende. Kommt danach etwas anderes als Leerzeichen, Tabulator, Zeilenumbruch oder Wagenrücklauf, bricht er ab.
{"a": 1}{"b": 2}
Der erste Wert {"a": 1} ist in Ordnung und endet bei Position 7. An Position 8 beginnt {"b": 2}. Das ist der überzählige Teil.
Die Position zählt ab 0, nicht ab 1. Mehr dazu steht in JSON-Fehler finden und beheben.
Die Meldung in verschiedenen Umgebungen
Je nach Laufzeit und Version sieht der Text anders aus. Für das Beispiel {"a": 1}{"b": 2}:
| Umgebung | Meldung |
|---|---|
| Node.js und Chrome (V8), aktuelle Versionen | Unexpected non-whitespace character after JSON at position 8 |
| Firefox | JSON.parse: unexpected non-whitespace character after JSON data at line 1 column 9 of the JSON data |
Python (json) |
json.decoder.JSONDecodeError: Extra data: line 1 column 9 (char 8) |
Aktuelle Node-Versionen (getestet mit Node 26) hängen an die V8-Meldung noch (line 1 column 9) an. Ältere V8-Versionen sagten stattdessen Unexpected token { in JSON at position 8. Die genaue Formulierung hängt also von der Version ab, die Ursache ist dieselbe. Zur Python-Variante gibt es einen eigenen Ratgeber: JSONDecodeError in Python.
Ursache 1: Zwei JSON-Werte hintereinander
Der häufigste Fall: Zwei Objekte oder Arrays stehen ohne Trennung nebeneinander. Das passiert, wenn Programme mehrfach in dieselbe Datei oder Antwort schreiben oder wenn Texte per Hand zusammenkopiert werden.
{"id": 1, "name": "Ada"}{"id": 2, "name": "Linus"}
Ein Komma dazwischen hilft nicht, denn {"a": 1},{"b": 2} ist als Ganzes ebenfalls kein gültiges JSON. Du brauchst ein umschließendes Array:
[
{"id": 1, "name": "Ada"},
{"id": 2, "name": "Linus"}
]
Wenn du den Text vor dem Parsen selbst zusammensetzt, sammle die Werte in einer Liste und serialisiere sie einmal, statt mehrere Dokumente zu verketten.
Ursache 2: NDJSON / JSON Lines als ein Dokument gelesen
Bei NDJSON (auch JSON Lines) steht pro Zeile ein eigener JSON-Wert. Das Format ist üblich bei Log-Exporten, Datenbank-Dumps und Streaming-Schnittstellen. Als Ganzes ist es kein gültiges JSON:
{"id": 1, "event": "login"}
{"id": 2, "event": "logout"}
Der Parser liest die erste Zeile, trifft in Zeile 2 auf { und meldet den Fehler. Lösung: zeilenweise parsen.
// ES-Modul (.mjs oder "type": "module"), wegen await auf oberster Ebene
import fs from "node:fs";
const text = await fs.promises.readFile("events.ndjson", "utf8");
const events = text
.split("\n")
.filter((line) => line.trim() !== "")
.map((line) => JSON.parse(line));
In Python:
import json
with open("events.ndjson", encoding="utf-8") as f:
events = [json.loads(line) for line in f if line.strip()]
Auf der Kommandozeile fasst jq mit -s („slurp“) alle Zeilen in einem Array zusammen:
jq -s -c . events.ndjson
Das Ergebnis ist ein gültiges JSON-Array, das du im JSON-Formatierer prüfen kannst.
Ursache 3: Zusätzlicher Text hinter dem JSON
Manchmal hängt hinter dem JSON etwas, das nicht dazugehört: eine Log-Zeile, eine Debug-Ausgabe, ein Semikolon oder eine Warnung des Servers.
{"status": "ok"}
Server started on port 3000
Typische Quellen:
- Ein Skript gibt mit
printoderconsole.logDebug-Text auf derselben Ausgabe aus wie das JSON. - Ein PHP- oder Server-Fehler schreibt eine Warnung vor oder hinter die Antwort.
- Ein Semikolon bleibt von JSONP oder einer JavaScript-Zuweisung (
var x = {...};) übrig. - Ein Null-Byte oder anderes unsichtbares Zeichen hängt am Ende der Datei.
Lösung: Debug-Ausgaben auf stderr umleiten oder entfernen, bis auf der Ausgabe nur noch das JSON steht. Prüfe in den Entwicklertools (Tab „Netzwerk“, Antwort), was der Server wirklich schickt. Schau dir dort den Rohtext an, nicht nur die Vorschau.
Ursache 4: Anführungszeichen im verschachtelten JSON
Wer JSON als Text in JSON einbettet, muss die inneren Anführungszeichen maskieren. Sonst endet der äußere String zu früh:
"{"a":1}"
Der Parser liest "{" als vollständigen String. Danach folgt a, und genau dort meldet er den Fehler (Position 3). Korrekt maskiert wäre es:
"{\"a\":1}"
Das ist gültiges JSON, der Wert ist ein String. Um an das innere Objekt zu kommen, parst du zweimal:
const inner = JSON.parse(JSON.parse(raw));
Doppelt kodiertes JSON löst für sich genommen diesen Fehler nicht aus, es ergibt nur einen String statt eines Objekts. Der Fehler entsteht erst, wenn beim Einbetten die Maskierung fehlt oder wenn dieselbe Antwort zweimal hintereinander geschrieben wird (siehe Ursache 1). Mehr zu Anführungszeichen: Anführungszeichen in JSON.
Ursache 5: Überzählige schließende Klammer
Eine Klammer zu viel am Ende reicht aus:
{"a": 1}}
[1, 2]]
Der Parser ist nach der ersten schließenden Klammer fertig und findet danach noch } oder ]. Das passiert oft beim Löschen oder Verschieben von Blöcken. Entferne die überzählige Klammer. Im Formatierer siehst du an der Einrückung, wo die Struktur nicht mehr stimmt.
Mehrere Werte bewusst verarbeiten
Manchmal willst du tatsächlich mehrere aneinandergehängte Werte lesen, etwa wenn du Logs ohne Zeilenumbrüche bekommst. In Python geht das mit raw_decode, das den Wert liest und die Endposition zurückgibt:
import json
text = '{"a": 1}{"b": 2}'
decoder = json.JSONDecoder()
pos = 0
values = []
while pos < len(text):
value, pos = decoder.raw_decode(text, pos)
values.append(value)
while pos < len(text) and text[pos].isspace():
pos += 1
print(values) # [{'a': 1}, {'b': 2}]
Das ist eine Notlösung. Besser ist es, die Quelle so zu ändern, dass sie ein Array oder NDJSON mit einem Wert pro Zeile liefert.
So gehst du vor
- Füge den Text in den JSON-Formatierer ein und schau dir die gemeldete Position an.
- Sieh dir das Zeichen an dieser Stelle an:
{oder[deutet auf zwei Werte oder NDJSON hin,}oder]auf eine überzählige Klammer, Buchstaben auf Log-Text. - Prüfe, woher der Text stammt. Wenn er aus einer Datei oder Antwort kommt, schau dir das Ende an, nicht nur den Anfang.
- Behebe die Ursache an der Quelle, statt den Text im Code zurechtzuschneiden.
Kurz gesagt
- Die Meldung bedeutet: Nach einem vollständigen JSON-Wert steht noch etwas, das kein Leerraum ist.
- Häufige Ursachen: zwei Werte hintereinander, NDJSON als ein Dokument gelesen, Log-Text oder Semikolon am Ende, falsch maskierte Anführungszeichen, eine Klammer zu viel.
- NDJSON parst du zeilenweise; mehrere Objekte packst du in ein Array.
- Firefox sagt „unexpected non-whitespace character after JSON data“, Python „Extra data“. Gemeint ist dasselbe.
- Die Position zählt ab 0 und zeigt den Beginn des überzähligen Teils.
Weiterlesen: Unexpected token in JSON, JSONDecodeError in Python, JSON-Fehler finden und beheben und der JSON-Formatierer.