BOM am Dateianfang: „Unexpected token“ an Position 0 in JSON beheben

Ein BOM (Byte Order Mark) ist ein unsichtbares Zeichen am Anfang einer Datei. Viele JSON-Parser lehnen es ab und melden einen Fehler schon an Position 0, obwohl das JSON im Editor völlig korrekt aussieht. Die Lösung: Datei als „UTF-8 ohne BOM“ speichern oder das BOM vor dem Parsen entfernen. Beides zeigt dieser Ratgeber.

Zum Prüfen kannst du den Text in den JSON-Formatierer einfügen. Er überspringt ein BOM am Anfang und zeigt dir echte Syntaxfehler mit Zeile und Spalte. Die Verarbeitung läuft komplett lokal im Browser, es wird nichts an einen Server gesendet.

Was ein BOM ist

Das BOM ist das Unicode-Zeichen U+FEFF. In UTF-16 und UTF-32 verrät es die Byte-Reihenfolge (daher der Name). In UTF-8 gibt es nur eine Byte-Reihenfolge, deshalb ist das BOM dort überflüssig. Es wird als die drei Bytes EF BB BF gespeichert und dient höchstens als Erkennungsmerkmal „diese Datei ist UTF-8“.

Im Editor siehst du davon nichts: Das Zeichen hat keine Breite und steht vor der ersten Klammer { oder [. Für einen Parser ist es aber ein Zeichen wie jedes andere, und JSON erlaubt als erstes Zeichen nur Leerraum oder einen Wert.

Was der Standard sagt

RFC 8259 (Abschnitt 8.1) legt zwei Dinge fest:

  • JSON-Text, der über ein Netzwerk übertragen wird, muss UTF-8 sein. Implementierungen, die JSON erzeugen, dürfen kein BOM davor setzen („MUST NOT“).
  • Implementierungen, die JSON lesen, dürfen ein BOM ignorieren, statt es als Fehler zu behandeln („MAY“). Sie müssen es aber nicht.

Eine Datei mit BOM ist also kein sauberes JSON, und ein Parser darf sie ablehnen. Viele tun das, andere nicht. Deshalb funktioniert dieselbe Datei in einem Programm und scheitert im nächsten.

So zeigt sich der Fehler

Typisch ist ein Fehler an der allerersten Stelle. Die genaue Meldung hängt von Laufzeit und Version ab. Beispiele:

Unexpected token '', "{"a":1}" is not valid JSON      (Chrome/Node.js, neuere Versionen)
Unexpected UTF-8 BOM (decode using utf-8-sig): line 1 column 1 (char 0)   (Python)

Bei der Chrome/Node.js-Meldung steht zwischen den Anführungszeichen scheinbar nichts: Dort steckt das unsichtbare U+FEFF. Ältere Versionen melden ähnlich Unexpected token in JSON at position 0, mit dem unsichtbaren U+FEFF direkt nach „token“. Firefox und Safari formulieren anders.

Typische Merkmale:

  • Die Position ist 0 bzw. Zeile 1, Spalte 1.
  • Das JSON sieht im Editor und im JSON-Formatierer fehlerfrei aus.
  • Das Problem tritt nur mit Dateien aus bestimmten Quellen auf.

Andere Ursachen für „Unexpected token“ erklärt der Ratgeber „Unexpected token“ in JSON.

Woher das BOM kommt

  • Windows-Editoren und -Exporte. Ältere Versionen des Windows-Editors speicherten „UTF-8“ mit BOM. In neueren Versionen ist „UTF-8“ ohne BOM, „UTF-8 mit BOM“ ist eine eigene Auswahl. Auch Notepad++ und andere Editoren können je nach Einstellung ein BOM schreiben.
  • PowerShell 5.1. In Windows PowerShell 5.1 schreiben Out-File -Encoding UTF8 und Set-Content -Encoding UTF8 immer ein BOM. Die Umleitung > und Out-File ohne Parameter schreiben sogar UTF-16 (ebenfalls mit BOM).
  • Programme und Skripte anderer Hersteller, die „UTF-8“ pauschal mit BOM speichern.

Ein typischer Fall:

# Windows PowerShell 5.1: erzeugt eine Datei MIT BOM
$daten | ConvertTo-Json | Out-File -Encoding UTF8 config.json

BOM erkennen

Prüfe die ersten Bytes. Eine Datei mit BOM beginnt mit ef bb bf:

head -c 3 config.json | xxd
# 00000000: efbb bf                                  ...

Auf vielen Systemen meldet auch file config.json etwas wie „UTF-8 (with BOM) text“. In VS Code zeigt die Statusleiste unten rechts „UTF-8 with BOM“ statt „UTF-8“.

In JavaScript prüfst du das erste Zeichen:

text.charCodeAt(0) === 0xFEFF; // true bei BOM

BOM entfernen

VS Code

  1. Klicke in der Statusleiste auf die Kodierung („UTF-8 with BOM“).
  2. Wähle Mit Kodierung speichern (Save with Encoding).
  3. Wähle UTF-8.

Damit neue Dateien nie ein BOM bekommen, achte darauf, dass die Einstellung files.encoding auf utf8 steht (nicht utf8bom).

Notepad++

Öffne das Menü Kodierung (Encoding). Dort ist die aktuelle Kodierung markiert, bei BOM-Dateien „UTF-8-BOM“. Wähle stattdessen „Konvertiere zu UTF-8“ und speichere. Die Menütexte unterscheiden sich zwischen Versionen und Spracheinstellungen.

PowerShell

In PowerShell 7 schreibt -Encoding utf8 standardmäßig ohne BOM. Es gibt außerdem die expliziten Werte utf8NoBOM und utf8BOM:

# PowerShell 7+
$daten | ConvertTo-Json | Set-Content -Encoding utf8NoBOM config.json

Windows PowerShell 5.1 kennt utf8NoBOM nicht. Dort gehst du über .NET, dessen WriteAllText ohne Angabe UTF-8 ohne BOM verwendet:

# Windows PowerShell 5.1
$json = $daten | ConvertTo-Json
[System.IO.File]::WriteAllText("$PWD\config.json", $json)

Ein vorhandenes BOM entfernst du so. Der Pfad wird vollständig angegeben, weil .NET das aktuelle PowerShell-Verzeichnis nicht kennt:

$pfad = Join-Path $PWD "config.json"
$text = Get-Content -Raw $pfad
[System.IO.File]::WriteAllText($pfad, $text)

Get-Content erkennt das BOM beim Lesen und verwirft es, das Zurückschreiben erfolgt ohne BOM.

Kommandozeile mit sed

Mit GNU sed (Linux):

sed -i '1s/^\xEF\xBB\xBF//' config.json

Die macOS-Variante von sed versteht \x-Schreibweise nicht von sich aus. In zsh oder bash funktioniert:

sed -i '' #39;1s/^\xEF\xBB\xBF//' config.json

Alternativ schneidest du die ersten drei Bytes ab, aber nur, wenn du vorher geprüft hast, dass sie wirklich ein BOM sind:

tail -c +4 config.json > config-ohne-bom.json

In JavaScript

Entferne das BOM, bevor du parst:

import { readFileSync } from "node:fs";

const text = readFileSync("config.json", "utf8");
const daten = JSON.parse(text.replace(/^\uFEFF/, ""));

readFileSync mit "utf8" behält das BOM als Zeichen U+FEFF im String, deshalb scheitert JSON.parse ohne diesen Schritt. Schreibe das Muster als \uFEFF, nicht als eingefügtes unsichtbares Zeichen: Das literale Zeichen übersteht Copy-and-paste und Formatierer oft nicht.

In Python

Öffne die Datei mit der Kodierung utf-8-sig. Sie entfernt ein vorhandenes BOM und funktioniert auch bei Dateien ohne BOM:

import json

with open("config.json", encoding="utf-8-sig") as f:
    daten = json.load(f)

BOM dauerhaft vermeiden

  • Speichere JSON immer als „UTF-8“ ohne BOM, besonders für Web-APIs, Konfigurationsdateien und Dateien im Repository.
  • Verwende in PowerShell 5.1 nicht -Encoding UTF8 für JSON, sondern den .NET-Weg von oben oder gleich PowerShell 7.
  • Wenn du JSON selbst auslieferst, schreibe kein BOM in die Antwort. RFC 8259 verbietet das ausdrücklich.
  • Wenn Dateien von Dritten kommen und du sie lesen musst, entferne das BOM beim Einlesen. Das ist robuster als darauf zu hoffen, dass es nie auftaucht.

Kurz gesagt

  • Ein BOM ist das unsichtbare Zeichen U+FEFF (Bytes EF BB BF) am Dateianfang und in UTF-8 überflüssig.
  • RFC 8259 verbietet, es beim Erzeugen von JSON für Netzwerke hinzuzufügen. Parser dürfen es ignorieren, müssen aber nicht.
  • Der Fehler tritt an Position 0 auf, obwohl das JSON korrekt aussieht.
  • Du entfernst es in VS Code über „Mit Kodierung speichern“ → UTF-8, in PowerShell 7 mit utf8NoBOM, per sed oder im Code mit .replace(/^\uFEFF/, ''); in Python liest du mit utf-8-sig.

Weiterführend: JSON-Fehler finden und beheben, „Unexpected token“ in JSON, JSON-Datei öffnen und der JSON-Formatierer.