So behandeln Sie Uncaught (in promise) TypeError
Sie debuggen Ihre Frontend-Anwendung, als die Konsole anzeigt: Uncaught (in promise) TypeError: Cannot read property 'type' of undefined. Diese Fehlermeldung enthält zwei unterschiedliche Probleme, die Entwickler oft verwechseln. Das Verständnis beider ist für die korrekte Fehlerbehandlung von JavaScript Promises unerlässlich.
Dieser Artikel erklärt, was dieser Fehler tatsächlich bedeutet, warum er auftritt und wie Sie nicht behandelte Promise-Ablehnungen in Browser-Umgebungen richtig handhaben.
Wichtigste Erkenntnisse
- Die Meldung „Uncaught (in promise) TypeError” signalisiert zwei separate Probleme: einen Laufzeit-TypeError und einen fehlenden Promise-Rejection-Handler.
- Häufige Ursachen sind schwebende Promises (fehlendes
await), vergessene.catch()-Handler und der Zugriff auf Eigenschaften vonundefinedodernull. - Umschließen Sie
await-Ausdrücke mittry/catchoder fügen Sie.catch()am Ende jeder Promise-Kette hinzu, um nicht behandelte Ablehnungen zu verhindern. - Verwenden Sie Optional Chaining (
?.) und Nullish Coalescing (??), um sich vor TypeErrors durch undefinierte Eigenschaften zu schützen. - Reservieren Sie das
unhandledrejection-Event für Monitoring und Telemetrie, nicht als Ersatz für lokale Fehlerbehandlung.
Was ‘Uncaught (in promise) TypeError’ tatsächlich bedeutet
Diese Fehlermeldung kommuniziert zwei separate Probleme:
- TypeError: Ein Laufzeitfehler ist aufgetreten – typischerweise durch den Zugriff auf eine Eigenschaft von
undefinedodernull. - Uncaught (in promise): Das Promise, das diesen Fehler erzeugt hat, hatte keinen Rejection-Handler angehängt.
Der Browser unterscheidet diese, weil Promise-Ablehnungen sich anders verhalten als synchrone Fehler. Wenn ein synchroner TypeError auftritt, stoppt die Ausführung sofort. Wenn derselbe Fehler innerhalb eines Promise auftritt, propagiert die Ablehnung durch die Promise-Kette. Wenn kein .catch() oder try/catch ihn behandelt, protokolliert der Browser ihn als nicht behandelte Promise-Ablehnung.
Für eine ausführlichere Referenz zum Promise-Verhalten und zur Fehlerpropagierung siehe die MDN-Dokumentation zu Promises.
Häufige Grundursachen in Frontend-Code
Fehler, die innerhalb von Async-Funktionen geworfen werden
Jede Exception innerhalb einer async-Funktion lehnt automatisch das zurückgegebene Promise ab:
async function fetchUserData(userId) {
const response = await fetch(`/api/users/${userId}`)
const data = await response.json()
return data.profile.name // TypeError, wenn profile undefined ist
}
fetchUserData(123) // Schwebendes Promise – kein Handler angehängt
Fehlende Await-Schlüsselwörter
Das Vergessen von await erzeugt ein schwebendes Promise, das unabhängig ausgeführt wird:
async function processData() {
fetchUserData(123) // Fehlendes await – Ablehnung bleibt unbehandelt
console.log('Done')
}
Vergessene .catch()-Handler
Promise-Ketten ohne einen abschließenden .catch()-Block lassen Ablehnungen unbehandelt:
fetch('/api/data')
.then(res => res.json())
.then(data => data.items[0].name) // Kein .catch() – TypeError propagiert
Spätes Anhängen von Handlern und Microtask-Timing
Browser bestimmen, ob eine Ablehnung behandelt wird, nach dem aktuellen Microtask-Checkpoint. Wenn eine Ablehnung zu diesem Zeitpunkt keinen Handler hat, kann der Browser ein unhandledrejection-Event auslösen und eine Konsolenwarnung protokollieren. Das nachträgliche Anhängen eines Handlers kann dennoch die Warnung in Entwicklungs-Builds auslösen:
const promise = Promise.reject(new Error('Failed'))
promise.catch(err => console.log('Handled'))
Diese Timing-Nuance erklärt, warum einige korrekt behandelte Ablehnungen während der Entwicklung dennoch als unbehandelt erscheinen können.
Discover how at OpenReplay.com.
Korrekte Async/Await-Fehlerbehandlungsmuster
Lokales try/catch um Await
Das zuverlässigste Muster umschließt await-Ausdrücke mit try/catch:
async function fetchPokemon(id) {
try {
const response = await fetch(`https://pokeapi.co/api/v2/pokemon/${id}`)
const data = await response.json()
return {
name: data.name,
type: data.types[0]?.type.name,
type2: data.types[1]?.type.name ?? null
}
} catch (error) {
console.error('Fetch failed:', error.message)
return null
}
}
Rückgabe von Promises mit angehängten Handlern
Behandeln Sie beim Aufruf von Async-Funktionen immer das zurückgegebene Promise:
// Option 1: await mit try/catch
await fetchPokemon(25)
// Option 2: .catch() beim Aufruf
fetchPokemon(25).catch(handleError)
Angemessenes Verketten von .catch()
Platzieren Sie .catch() am Ende von Promise-Ketten, um jede Ablehnung in der Kette abzufangen:
Promise.all(urls.map(url => fetch(url).then(r => r.json())))
.then(results => processResults(results))
.catch(error => showErrorUI(error))
Verwendung des unhandledrejection-Events für Monitoring
Browser stellen das unhandledrejection-Event für globales Fehler-Monitoring bereit – nicht als primären Fehlerbehandlungsmechanismus:
window.addEventListener('unhandledrejection', event => {
// An Error-Monitoring-Service protokollieren
errorTracker.capture(event.reason)
// Optional den Standard-Konsolenfehler verhindern
event.preventDefault()
})
Das zugehörige rejectionhandled-Event wird ausgelöst, wenn eine zuvor unbehandelte Ablehnung später einen Handler erhält. Diese Events sind nützlich für Telemetrie und zum Abfangen von Fehlern, die durch Ihre lokale Behandlung schlüpfen, sollten aber nicht die korrekten try/catch- und .catch()-Muster ersetzen.
Fazit
Die Meldung „Uncaught (in promise) TypeError” signalisiert sowohl einen Laufzeitfehler als auch fehlende Fehlerbehandlung. Adressieren Sie beide Seiten des Problems: Verwenden Sie Optional Chaining (?.) und Nullish Coalescing (??), um TypeErrors durch undefinierte Eigenschaften zu verhindern, und umschließen Sie asynchrone Operationen mit try/catch oder fügen Sie .catch()-Handler an jede Promise-Kette an. Reservieren Sie das unhandledrejection-Event für Monitoring, nicht für den Kontrollfluss. Diese Muster halten Ihren Frontend-Code robust und Ihre Konsole sauber.
FAQs
Ein Uncaught TypeError ist ein synchroner Fehler, der die Ausführung sofort stoppt. Ein Uncaught (in promise) TypeError ist dieselbe Art von Laufzeitfehler, trat jedoch innerhalb eines Promise auf, das keinen Rejection-Handler hatte. Der Browser fügt die Kennzeichnung 'in promise' hinzu, um anzuzeigen, dass die Ablehnung in der asynchronen Promise-Kette unbehandelt blieb.
Ja. Ein einzelnes .catch() am Ende einer Promise-Kette fängt jede Ablehnung ab, die in einem vorangehenden .then()-Callback auftritt. Die Ablehnung propagiert durch die Kette, bis sie einen .catch()-Handler findet. Wenn keiner existiert, meldet der Browser sie als nicht behandelte Promise-Ablehnung.
Ein try/catch-Block innerhalb eines .then()-Callbacks kann synchrone Fehler abfangen, die innerhalb dieses Callbacks geworfen werden. Er kann jedoch keine Promise-Ablehnungen abfangen, es sei denn, diese Promises werden innerhalb einer Async-Funktion mit await erwartet. Um Ablehnungen in einer .then()-Kette zu behandeln, fügen Sie ein .catch() am Ende der Kette hinzu. Reservieren Sie try/catch primär für Async/Await-Muster.
Nein. Das unhandledrejection-Event ist ein Sicherheitsnetz zum Abfangen von Promise-Ablehnungen, die durch Ihre lokale Fehlerbehandlung schlüpfen. Es eignet sich am besten für Protokollierung und Monitoring. Behandeln Sie Fehler immer zuerst lokal mit try/catch oder .catch() und betrachten Sie den globalen Event-Listener als Fallback für die Diagnose.
Complete picture for complete understanding
Capture every clue your frontend is leaving so you can instantly get to the root cause of any issue with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data.
Check our GitHub repo and join the thousands of developers in our community.