YAML: „found character that cannot start any token“ beheben
Die Meldung found character '\t' that cannot start any token heißt: Der YAML-Parser ist auf ein Zeichen gestoßen, mit dem an dieser Stelle kein gültiges Element beginnen kann. Die häufigste Ursache ist ein Tabulator zum Einrücken, YAML erlaubt dafür nur Leerzeichen. Andere häufige Ursachen sind ein @, ein Backtick ` oder ein % am Anfang eines unquotierten Werts. Die Lösung: Tabs durch Leerzeichen ersetzen, den Wert in Anführungszeichen setzen.
Die Meldung stammt aus libyaml und PyYAML und taucht deshalb auch in Ruby, Go-basierten Tools wie Helm und anderen auf. Sie nennt Zeile und Spalte. Die reine Python-Variante von PyYAML zeigt zusätzlich das Zeichen in Anführungszeichen, bei einem Tab als '\t'; libyaml lässt es weg. Wenn du das YAML in den YAML-Formatierer einfügst, kannst du die Einrückung danach sauber neu setzen; Kommentare bleiben erhalten. Die Verarbeitung läuft komplett lokal im Browser, es wird nichts an einen Server gesendet.
Typische Fehlermeldung
PyYAML 6.0 gibt bei einer Datei mit Tab-Einrückung Folgendes aus:
yaml.scanner.ScannerError: while scanning for the next token
found character '\t' that cannot start any token
in "<unicode string>", line 2, column 1:
b: 1
^
Bei Dateien steht statt <unicode string> der Dateiname. „Line 2, column 1“ zählt ab 1. Der Pfeil zeigt auf das Zeichen, das der Parser nicht annimmt. Diese Formulierung mit Zeichen stammt aus dem reinen Python-Loader von PyYAML (SafeLoader); mit libyaml (CSafeLoader) fehlt das Zeichen. Andere Parser formulieren anders, siehe den Abschnitt Andere Parser.
Ursache 1: Tabulator als Einrückung
server:
host: localhost
port: 8080
In diesem Beispiel stehen vor host und port echte Tabs. YAML definiert die Struktur über die Einrückung, und die Spezifikation verbietet Tabs dort ausdrücklich. Im Editor sehen Tabs und Leerzeichen oft gleich aus, deshalb fällt der Fehler erst beim Parsen auf.
Behoben mit zwei Leerzeichen pro Ebene:
server:
host: localhost
port: 8080
Tabs verursachen die Meldung auch an Stellen, an denen sie die Einrückung gar nicht betreffen:
name: Ada # Tab nach dem Doppelpunkt
liste: [1, 2] # Tab in einer Flow-Liste
Laut YAML-1.2-Spezifikation sind Tabs als Trenner innerhalb einer Zeile teilweise erlaubt. Der reine Python-Loader von PyYAML (yaml.safe_load) ist hier strenger und lehnt sie ab; mit libyaml (CSafeLoader) werden sie akzeptiert (getestet mit PyYAML 6.0.3). Auch eine „leere“ Zeile, die nur aus einem Tab besteht, löst den Fehler aus. Ersetze solche Tabs ebenfalls durch Leerzeichen.
Tabs finden
Im Editor: Aktiviere die Anzeige von Leerraum. In VS Code heißt die Einstellung editor.renderWhitespace (Werte all oder boundary); Tabs erscheinen als Pfeil →, Leerzeichen als Punkt. Um dem Problem vorzubeugen, stellst du editor.insertSpaces auf true, dann fügt die Tab-Taste Leerzeichen ein. Über die Befehlspalette stellst du mit dem Befehl „Convert Indentation to Spaces“ die ganze Datei um.
Auf der Kommandozeile:
# Zeilen mit Tab anzeigen (nur GNU grep, nicht macOS)
grep -nP '\t' config.yaml
# funktioniert mit GNU und macOS grep in bash und zsh
grep -n #39;\t' config.yaml
# Tabs sichtbar machen: ^I steht für einen Tab, $ markiert das Zeilenende
cat -A config.yaml # GNU/Linux
cat -et config.yaml # macOS (BSD cat)
Tabs automatisch ersetzen (Tab-Stopps alle zwei Spalten, ein Tab am Zeilenanfang wird also zu zwei Leerzeichen; prüfe das Ergebnis, denn gemischte Einrückung kann dadurch die Struktur verschieben):
expand -t 2 config.yaml > config.fixed.yaml
expand wandelt Tabs in Leerzeichen bis zum nächsten Tab-Stopp um. Bei sauber mit einem Tab pro Ebene eingerückten Dateien entsteht so eine gültige Zwei-Leerzeichen-Einrückung.
Ursache 2: @ oder Backtick am Wertanfang
Die Zeichen @ und ` sind in YAML als Indikatoren reserviert. Ein unquotierter (plain) Wert darf nicht damit beginnen:
paket: @scope/name
befehl: `date`
PyYAML meldet found character '@' that cannot start any token beziehungsweise dasselbe für '`'. Das typische Muster: npm-Paketnamen mit Scope, Shell-Befehle oder Template-Platzhalter, die jemand ungeschützt in die Datei kopiert hat.
Behoben durch Anführungszeichen:
paket: "@scope/name"
befehl: "`date`"
Mitten im Wert sind beide Zeichen unproblematisch: mail: ada@example.org und befehl: a`b werden korrekt gelesen. Nur am Anfang eines unquotierten Skalars sind sie verboten.
Ursache 3: % am Wertanfang und Direktiven
Das Prozentzeichen leitet in YAML eine Direktive ein, etwa %YAML 1.2. Direktiven sind nur am Zeilenanfang vor dem Dokumentstart --- erlaubt. Als Beginn eines Werts ist % verboten:
rabatt: %20
rabatt: "%20"
Auch hier gilt: rabatt: 20% ist gültig, weil das Zeichen nicht am Anfang steht. Steht dagegen eine Zeile mit % am Anfang einer Datei ohne passendes ---, kommt eine andere Meldung, weil der Parser die Zeile als Direktive liest: in PyYAML etwa expected '<document start>', mit libyaml found unknown directive name.
Weitere Zeichen
Dieselbe Fehlerklasse betrifft jedes Zeichen, das der Parser an dieser Stelle nicht verarbeiten kann. Typische Fälle:
*oder&ohne Namen dahinter melden einen anderen Fehler (while scanning an aliasbeziehungsweisean anchor), weil sie Aliase und Anker einleiten. Wert in Anführungszeichen setzen, wenn du das Zeichen wörtlich meinst.- Ein Wert, der mit
{,[,"oder'beginnt, wird als Flow-Syntax oder quotierter String gelesen. Fehlt das schließende Zeichen, kommt ein Fehler wieexpected ',' or '}'. - Steuerzeichen und unsichtbare Sonderzeichen aus kopierten Texten. Im Test liest PyYAML ein führendes BOM und geschützte Leerzeichen (U+00A0) im Wert ohne Fehler, andere Parser sind teils strenger. Wenn du nichts Auffälliges findest, hilft
cat -Aoder die Whitespace-Anzeige des Editors.
Allgemein gilt: Wenn ein Wert mit einem Sonderzeichen beginnt, setze ihn in doppelte Anführungszeichen. Das ist immer gültig. Für Backslashes und Zeilenumbrüche beachte die Escape-Regeln in "..."; wenn du lieber nichts escapen willst, nimm einfache Anführungszeichen '...'.
Andere Parser
Die exakte Meldung hängt vom Parser und seiner Version ab:
- PyYAML (Python):
found character '\t' that cannot start any token, wie oben getestet. - js-yaml (JavaScript) und andere Parser formulieren anders, zum Beispiel mit Hinweisen auf falsche Einrückung oder ein unerwartetes Zeichen. Der genaue Wortlaut variiert je nach Version. Die Ursachen sind dieselben, und die Zeilenangabe führt dich zur Stelle.
- Manche Parser akzeptieren Tabs an Stellen, an denen PyYAML scheitert, etwa nach einem Doppelpunkt. Auch die Werkzeuge von formatierer.de (YAML 1.2) akzeptieren einen Tab nach dem Doppelpunkt; einen Tab in der Einrückung melden sie mit Zeile und Spalte. Verlass dich nicht darauf: Eine Datei, die bei dir läuft, kann in einem anderen Tool abgelehnt werden. Spaces sind überall sicher.
Um zu prüfen, ob dein korrigiertes YAML als Datenstruktur stimmt, wandle es im YAML-zu-JSON-Konverter um. Landet jeder Wert dort unter dem richtigen Schlüssel, ist Einrückung und Quoting in Ordnung.
Vorgehen in drei Schritten
- Lies Zeile und Spalte aus der Meldung und schau dir dort das Zeichen an.
- Steht dort ein Tab (Meldung
'\t'): Whitespace sichtbar machen oder mitgrep -n #39;\t'alle Tabs finden und durch Leerzeichen ersetzen. - Steht dort
@,`oder%am Wertanfang: den Wert in Anführungszeichen setzen.
Einen Überblick über weitere Strukturfehler findest du im Ratgeber YAML-Fehler finden und beheben. Ein verwandter Fehler ist YAML: could not find expected ':'.
Kurz gesagt
- „Found character that cannot start any token“ bedeutet: Das Zeichen an der gemeldeten Stelle kann dort kein YAML-Element beginnen.
- Häufigste Ursache sind Tabs in der Einrückung. YAML verlangt Leerzeichen, in der Regel zwei pro Ebene.
@,`und%dürfen einen unquotierten Wert nicht einleiten. Setze den Wert in Anführungszeichen.- Tabs findest du mit
grep -n #39;\t',cat -A(Linux) beziehungsweisecat -et(macOS) oder der Whitespace-Anzeige deines Editors. - Der Wortlaut der Meldung unterscheidet sich zwischen Parsern, die Ursachen sind dieselben.
Weiterführend: YAML-Fehler finden und beheben, YAML: could not find expected ':', mehrzeilige Strings in YAML, Was ist YAML? und der YAML-Formatierer.