"Unexpected end of JSON input" — der Body war leer oder abgeschnitten
Dieser Fehler bedeutet, dass dem Parser der Text ausging, bevor die JSON-Struktur vollständig war. Fast immer war der Response-Body leer oder die Übertragung wurde abgeschnitten — und beide Fälle brauchen völlig unterschiedliche Lösungen.
Anders als die meisten JSON-Fehler nennt dieser kein Zeichen, weil kein Zeichen mehr übrig war, das er hätte nennen können. Der Parser erreichte das Ende der Eingabe, während er noch auf eine schließende Klammer oder ein schließendes Anführungszeichen wartete. Dein Parsing-Code ist in Ordnung — dir wurde weniger Text übergeben, als ein vollständiges JSON-Dokument ausmacht.
Die häufigste Ursache: der Body war komplett leer
JSON.parse("") wirft genau diesen Fehler, und ein leerer String kommt häufiger vor als man denkt. Eine 204-No-Content-Antwort hat per Definition keinen Body, was bei einem erfolgreichen DELETE oder PUT der Normalfall ist. Ein 304 Not Modified liefert ebenfalls nichts zurück, denn die Aussage ist ja gerade, dass dein Cache noch gültig ist. Eine HEAD-Anfrage liefert nie einen Body. Und eine Anfrage, die auf Netzwerkebene scheiterte — Verbindung abgelehnt, CORS-Preflight verweigert, Request abgebrochen — kann dir je nach Client einen leeren String statt einer Exception hinterlassen.
Die zweite Ursache: die Antwort wurde unterwegs abgeschnitten
Hier beginnt der Body als gültiges JSON und hört einfach mittendrin auf. Die Verbindung brach ab, ein Timeout griff, während die Antwort noch gestreamt wurde, oder etwas zwischen dir und dem Server erzwang ein Größenlimit — Reverse Proxies, nginx-Buffer-Einstellungen und Response-Limits von Serverless-Funktionen tun das stillschweigend. Ein nützliches Signal: Abschneiden ist meist sporadisch und korreliert mit der Größe. Kleine Antworten funktionieren, große scheitern. Wenn derselbe Endpunkt bei einem Datensatz sauber parst und bei tausend bricht, hast du ein Truncation-Problem, kein fehlerhaftes JSON.
Die dritte Ursache: Lesen aus Storage oder Datei
Kommt das JSON aus localStorage, einer Cache-Datei oder von der Festplatte, war womöglich das Schreiben die unvollständige Hälfte. localStorage schlägt still fehl, sobald das Kontingent überschritten ist, sodass ein großes Objekt halb geschrieben werden kann, ohne dass beim Schreiben eine Exception entsteht — der Fehler zeigt sich erst später beim Lesen. Eine Datei, die von einem abgestürzten Prozess oder auf einer vollgelaufenen Platte geschrieben wurde, führt zum selben Ergebnis. Das Unterscheidungsmerkmal: es schlägt jedes Mal identisch fehl, während ein Netzwerkabbruch meist sporadisch ist.
Wie du sie in einem Schritt auseinanderhältst
Gib vor dem JSON.parse die Länge des Rohwerts und seine letzten Zeichen aus. Länge null bedeutet leerer Body — dann solltest du den Statuscode behandeln statt überhaupt zu parsen. Eine Länge ungleich null, die nicht auf } oder ] endet, bedeutet Abschneiden; vergleiche dann die empfangene Länge mit dem Content-Length-Header. Wirkt die Länge vollständig und es scheitert trotzdem, liegt das Problem woanders im String und die Meldung hätte ein Zeichen genannt.
Die Lösung ist eine Guard-Klausel, kein try/catch
Der Reflex ist, das Parsen in try/catch zu wickeln und weiterzumachen, aber das verdeckt die eigentliche Bedingung und macht aus einem klaren Fehler einen stillen Leerzustand. Prüfe zuerst den Statuscode und behandle 204 und 304 explizit als "kein Body, und das ist korrekt". Vergewissere dich, dass die Antwort tatsächlich erfolgreich war, bevor du annimmst, es gäbe etwas zu parsen. Ein try/catch gehört um wirklich unerwartete, fehlerhafte Daten — nicht um den völlig vorhersehbaren Fall einer Antwort, die nie JSON enthalten sollte.
Wenn du den Rohtext hast und genau wissen willst, wo er aufhört gültig zu sein, füge ihn in unseren JSON-Validator ein — er nennt die Position, an der die Struktur abbricht, wodurch ein Abschneiden sofort erkennbar wird. Er läuft in deinem Browser, eine echte API-Antwort kannst du also gefahrlos einfügen.