Komunikat „unexpected token” sugeruje prosty błąd składni. W środowisku produkcyjnym przyczyna często znajduje się wcześniej: gateway zwrócił stronę HTML, połączenie ucięło body, log dopisał prefix albo bajty odczytano w złym charset. Skuteczna diagnoza zaczyna się od dokładnej odpowiedzi na pytanie, co naprawdę dotarło do parsera.

Najpierw należy zabezpieczyć surowe bajty

Konsola może interpretować escape, ucinać długi tekst i ukrywać znaki sterujące. Potrzebne są długość body, status, Content-Type i bezpieczna próbka oryginalnych bajtów. Dane wrażliwe trzeba zredagować i ograniczyć retencję.

Hexdump wokół pozycji błędu ujawnia BOM, null bytes, niepoprawny UTF-8 i nietypowe zakończenia linii. Dopiero wtedy wiadomo, czy wejście było JSON-em.

HTML zamiast JSON to częsty przypadek

Load balancer, system logowania lub webserver może wygenerować własną stronę błędu. Klient widzi pierwsze < i zgłasza problem parsowania. Prawdziwą przyczyną jest 502, redirect do logowania albo limit requestu.

Przed parse klient powinien sprawdzić status i typ treści. Przy niezgodności bezpieczna krótka próbka pomaga bardziej niż ogólne „invalid JSON”.

Ucięty dokument zwykle psuje się pod koniec

Brak zamykającej klamry nie musi oznaczać błędu producenta. Timeout, błędny Content-Length, przerwane połączenie lub pełny bufor mogą skrócić poprawną odpowiedź. Porównanie długości i logów infrastruktury oddziela problem transportu od serializacji.

Retry operacji zapisującej wymaga idempotency. Po uciętej odpowiedzi serwer mógł już wykonać działanie, a drugi request stworzy duplikat.

Trailing comma i komentarze nie należą do JSON

Literał JavaScript albo format JSON5 może pozwalać na komentarze, pojedyncze cudzysłowy czy przecinek po ostatnim elemencie. Standardowy JSON nie. Plik wyglądający poprawnie w edytorze może zostać słusznie odrzucony przez API.

Jeżeli kontrakt mówi JSON, należy naprawić producenta zamiast rozszerzać parser. Dla ręcznie edytowanej konfiguracji można świadomie wybrać inny format.

Stringi najczęściej psują escape

Surowy newline nie może wystąpić w stringu, a quote i backslash wymagają ucieczki. Ręczne sklejanie JSON działa do chwili, gdy użytkownik wpisze cudzysłów albo ścieżkę Windows.

Biblioteka serializująca powinna otrzymać strukturę danych i sama zbudować tekst. Template oraz replace nie obsługują poprawnie wszystkich znaków sterujących i Unicode.

Niepoprawny UTF-8 to osobna klasa błędu

JSON w web API jest zwykle UTF-8. Dane z legacy bazy lub pliku mogą pochodzić z Windows-1250 czy innego charsetu. Parser odrzuca bajty albo wcześniejsza warstwa zastępuje je znakami zastępczymi.

Naprawa powinna nastąpić przy źródle lub jawnej granicy importu. Losowe próby wielu decodingów mogą bezpowrotnie zmienić tekst.

Podwójna serializacja daje poprawny, ale zły typ

Czasem parser nie zgłasza błędu, lecz zwraca string zawierający kolejny dokument JSON. Dzieje się tak, gdy jedna warstwa już serializuje obiekt, a druga serializuje gotowy tekst. Widoczne backslashe przed każdym quote są typowym sygnałem.

Rozwiązaniem nie jest zawsze podwójny parse. Kontrakt musi wskazywać, czy funkcja przyjmuje obiekt, czy tekst JSON. Automatyczne wielokrotne dekodowanie może uruchomić interpretację treści, która miała pozostać zwykłym tekstem.

Zduplikowane klucze są semantycznie niebezpieczne

Biblioteki zachowują pierwszy, ostatni albo odrzucają obiekt z dwoma takimi samymi nazwami. Gateway i aplikacja mogą więc zobaczyć inne wartości. Atak wykorzystuje różnicę parserów bez łamania podstawowej składni.

Na granicy zaufania najbezpieczniej odrzucać duplikaty. Producent powinien serializować mapę lub typowany model, nie łączyć fragmenty stringów.

Duże liczby psują się już po udanym parse

64-bitowy identyfikator może zostać zaokrąglony w JavaScript. Dokument jest poprawny, ale później cache lub API szuka innego ID. Diagnostyka musi porównać wartość przed i po konwersji.

Duże ID należy transportować jako string, a dla decimal ustalić precyzję. Testy powinny zawierać granice, nie tylko małe liczby demonstracyjne.

Pozycję błędu trzeba odnieść do niezmienionego wejścia

Pretty-print przed analizą przesuwa offsety i może sam zawieść. Krótki fragment przed i po pozycji parsera zwykle pokazuje źle zamknięty string, brak przecinka lub niedokończony obiekt.

W UTF-8 offset bajtowy i numer widocznego znaku mogą się różnić. Narzędzie powinno jasno określać, którą jednostkę raportuje.

Strumień wielu dokumentów potrzebuje framingu

Kilka obiektów JSON zapisanych jeden po drugim nie tworzy jednego poprawnego dokumentu. NDJSON definiuje jeden obiekt na linię, inne protokoły używają prefiksu długości. Zwykły parser oczekuje pojedynczej wartości top-level.

Dopisanie tekstu logu przed payloadem również niszczy format. Metadane powinny znaleźć się w obiekcie opakowującym albo osobnym kanale.

Minimalny przypadek staje się testem regresji

Po zachowaniu oryginału można usuwać niezwiązane fragmenty, aż pozostanie najmniejszy input wywołujący problem. Pokazuje to, czy przyczyną jest znak, rozmiar, nesting czy konkretna biblioteka.

Fixture powinno trafić do repozytorium wraz z wersją parsera i ustawieniami. Dzięki temu następny refactor nie przywróci tej samej awarii.

Produkcję trzeba odtworzyć razem z nagłówkami

Sam body może parsować się lokalnie, podczas gdy błąd zależy od gzip, charsetu, redirectu lub middleware. Reprodukcja powinna zachować metodę, istotne nagłówki, status i kolejność proxy. Bez tego testuje się inny przypadek niż ten, który rzeczywiście zawiódł.

Bezpieczny zapis diagnostyczny może zastąpić sekrety wartościami o tej samej długości i typie. Pozwala to zachować strukturę bez przenoszenia danych klientów do środowiska deweloperskiego.

Walidacja schema następuje po parsowaniu

Poprawny JSON może nie zawierać wymaganych pól albo mieć zły typ. To błąd kontraktu, a nie składni. Odpowiedź powinna wyraźnie oddzielać transport, parse i walidację biznesową.

Solidny pipeline sprawdza status oraz bytes, potwierdza UTF-8, wykonuje ścisły parse, waliduje schema i dopiero uruchamia logikę. Taka kolejność zamienia niejasny błąd w konkretną naruszoną granicę.