Fehler sind Objekte mit einem Typ
Wenn JavaScript einen Fehler wirft, bekommst du keinen simplen String zurück, sondern ein Objekt. Dieses Objekt hat einen Typ (seinen Konstruktor) sowie ein paar Standard-Eigenschaften: name, message und stack.
err.name ist ein kurzes Label wie "TypeError". err.message ist die menschenlesbare Beschreibung. Mit err instanceof TypeError findest du heraus, um welche konkrete Klasse es sich handelt. Zu wissen, welcher JavaScript Fehlertyp vorliegt, ist wichtig: Es verrät dir, ob es um einen Tippfehler, einen falschen Wert oder um Code geht, der gar nicht erst geparst werden konnte.
Insgesamt gibt es sieben eingebaute JavaScript-Fehlertypen. Drei davon begegnen dir ständig, die anderen vier eher gelegentlich.
SyntaxError: Der Code ließ sich nicht parsen
Ein SyntaxError bedeutet, dass JavaScript deinen Code überhaupt nicht lesen konnte. Streng genommen ist das gar kein Laufzeitfehler — die Engine steigt schon beim Parsen aus, bevor auch nur eine einzige Zeile ausgeführt wird. Einen SyntaxError kannst du deshalb innerhalb derselben Datei nicht mit try/catch abfangen, weil die komplette Datei verworfen wird.
function greet(name {
return "hi, " + name;
}
// SyntaxError: Unexpected token '{'
Fehlende Klammer, ein verirrtes Komma, ein return außerhalb einer Funktion — alles, was die Grammatik verletzt, löst diesen Fehler aus. Abhilfe schafft nur eins: den Quellcode korrigieren. Einen SyntaxError wirklich abfangen kannst du nur an einer Stelle, nämlich wenn zur Laufzeit geparst wird, z. B. bei JSON.parse:
JSON.parse bekommt seinen String erst zur Laufzeit – Syntaxfehler darin lassen sich also abfangen. Syntaxfehler in deinen eigenen Quelldateien dagegen nicht.
ReferenceError: Diesen Namen gibt's nicht
Ein ReferenceError wird geworfen, sobald du auf eine Variable zugreifst, die in keinem für den aktuellen Code sichtbaren Scope deklariert wurde.
In neunzig Prozent der Fälle steckt einfach ein Tippfehler dahinter (totl statt total). Die restlichen zehn Prozent sind Scope-Probleme – du willst auf etwas zugreifen, das in einer anderen Funktion oder einem anderen Modul deklariert wurde.
Es gibt noch eine weniger offensichtliche Ursache: die temporal dead zone. Deklarationen mit let und const existieren zwar ab dem Anfang ihres Blocks, aber du kannst nicht darauf zugreifen, bevor die Zeile mit der Deklaration erreicht ist:
x ist zum Zeitpunkt von console.log(x) zwar bereits als Binding vorhanden, aber noch nicht initialisiert. Genau deshalb gibt's den Reference Error. Die Lösung: Den Zugriff einfach unter die Deklaration verschieben.
TypeError: Der Wert hatte die falsche Form
Ein TypeError bedeutet, dass ein Wert zwar existiert, aber nicht das ist, was die Operation erwartet. Etwas aufrufen, das keine Funktion ist, eine Eigenschaft von null oder undefined auslesen, einer const einen neuen Wert zuweisen – alles klassische TypeErrors.
„Cannot read properties of null (reading 'name')" dürfte mit Abstand die häufigste Fehlermeldung in JavaScript sein. Lösen lässt sich das auf zwei Arten: Entweder du stellst sicher, dass der Wert tatsächlich existiert, oder du sicherst den Zugriff per Optional Chaining ab – also user?.name.
Weitere typische Ausprägungen von TypeError:
Der Aufruf einer Zahl als Funktion, das Neuzuweisen einer const, oder das Aufrufen einer Methode, die gar nicht existiert — der Wert hatte schlicht den falschen Typ für das, was du von ihm wolltest.
RangeError: Zahl außerhalb des gültigen Bereichs
Ein RangeError wird geworfen, wenn eine Zahl zwar technisch gültig ist, aber außerhalb des erlaubten Bereichs für eine bestimmte Operation liegt.
Der Klassiker ist unendliche Rekursion — irgendwann ist der Call Stack voll:
„Maximum call stack size exceeded" ist fast immer ein Hinweis darauf, dass sich eine Funktion ohne Abbruchbedingung selbst aufruft – oder dass zwei Funktionen sich gegenseitig in einer Endlosschleife aufrufen.
URIError und EvalError: die Exoten
Ein URIError entsteht bei den URI-Hilfsfunktionen (encodeURI, decodeURIComponent und Co.), wenn man ihnen kaputte Eingaben vorsetzt:
EvalError ist ein Relikt aus alten Zeiten. Moderne JavaScript-Engines werfen diesen Fehler tatsächlich nirgendwo mehr – der Konstruktor existiert nur noch aus Gründen der Abwärtskompatibilität. Du kannst zwar manuell eine Instanz erzeugen, in freier Wildbahn wirst du ihm aber nicht begegnen.
Die Vererbungskette der Fehlerklassen
Alle diese Fehlertypen erben von einer gemeinsamen Basisklasse Error. Das bedeutet: err instanceof Error liefert für jeden von ihnen true – praktisch, wenn du in einem generischen catch-Block arbeitest:
Ein catch-Block fängt alles ab – auch Werte, die gar keine Fehler sind, etwa wenn jemand throw "oops" schreibt. Genau deshalb ist der letzte Zweig so wichtig: Prüfe einen gefangenen Wert immer erst mit instanceof, bevor du ihn wie ein Error-Objekt behandelst.
Fehler gezielt selbst werfen
Du kannst jeden der eingebauten Fehlertypen auch selbst werfen, sobald dein Code ein Problem erkennt. Wähle dabei den Typ, der am besten zur Fehlerursache passt:
Den Fehlertyp passend zur eigentlichen Ursache zu wählen, ist nicht bloß Kosmetik — erst dadurch können aufrufende Funktionen gezielt mit catch reagieren, statt Fehlermeldungen als Text zu zerpflücken.
Eigene Fehlerklasse in JavaScript definieren
Wenn keiner der eingebauten Typen wirklich passt, leitest du dir eine eigene Klasse von Error ab:
Zwei Dinge solltest du dir merken: Rufe super(message) auf, damit die Basisklasse Error sauber initialisiert wird, und setze this.name, damit in den Logs das passende Label erscheint. Mit eigenen Feldern wie field können aufrufende Stellen gezielt auf bestimmte Fehlerfälle reagieren, ohne Strings parsen zu müssen.
Weiter geht's: Konsole und DevTools
Die JavaScript-Fehlertypen zu kennen ist nur die halbe Miete – die andere Hälfte besteht darin, einen Stacktrace zu lesen und den Zustand zur Laufzeit zu inspizieren. Mit den DevTools des Browsers (und dem Debugger von Node) wird aus „irgendwas ist geflogen und ich hab keinen Plan warum" eine Sache von wenigen Sekunden. Darum geht's als Nächstes.
Häufig gestellte Fragen
Welche eingebauten Fehlertypen gibt es in JavaScript?
Insgesamt sieben: Error (die Basisklasse), SyntaxError, ReferenceError, TypeError, RangeError, URIError und EvalError. Jeder davon ist ein Konstruktor, der ein Fehlerobjekt mit den Eigenschaften name, message und stack erzeugt. Im Alltag begegnen dir vor allem SyntaxError, ReferenceError und TypeError.
Was ist der Unterschied zwischen SyntaxError und TypeError?
Ein SyntaxError heißt: Der Code ist kein gültiges JavaScript — die Engine kann ihn nicht mal parsen. Ein TypeError heißt dagegen: Der Code wurde sauber geparst, macht aber zur Laufzeit etwas Unerlaubtes, zum Beispiel eine Nicht-Funktion aufrufen oder auf eine Property von null zugreifen. Syntaxfehler stoppen das komplette Skript sofort, Typfehler treten erst auf, wenn die fehlerhafte Zeile tatsächlich ausgeführt wird.
Wann bekomme ich einen ReferenceError in JavaScript?
Immer dann, wenn du einen Namen verwendest, der nie deklariert wurde — oder wenn du eine let/const-Variable in ihrer Temporal Dead Zone ansprichst, also bevor die Deklaration erreicht ist. Die häufigste Ursache sind schlicht Tippfehler: consoel.log(x) wirft ReferenceError: consoel is not defined. Also zuerst Schreibweise und Scope prüfen.
Kann ich eigene Fehlertypen definieren?
Ja, einfach die eingebaute Error-Klasse erweitern: class ValidationError extends Error { }. Im Konstruktor solltest du this.name setzen, damit sich der Fehler später im Log und in catch-Zweigen sauber unterscheiden lässt. Lohnt sich immer dann, wenn verschiedene Fehler auch unterschiedlich behandelt werden sollen.