"Uncaught (in promise)" means a JavaScript Promise rejected, but no .catch() handler or try/catch existed to handle that rejection.
What "Uncaught (in promise)" Means
This is a runtime error in the browser console (Chrome, Firefox, Edge) and Node.js. It tells you a Promise failed, and the rejection went completely unhandled. Unlike synchronous errors that crash immediately, this one fires after the current call stack clears, leaving your application in an unknown state.
Why It Happens
The most common causes are:
- Forgotten error handling — you called an async function but never attached
.catch()or usedawaitinside atry/catch. - Event handler promises — promises created inside
onClick,setTimeout, or event listeners that reject without a handler. - Async function without try/catch — an
asyncfunction that throws internally but the caller doesn't handle the rejection.
Example Code That Triggers It
// Run this in a browser console or Node.js
async function fetchUserData() {
throw new Error("API returned 500");
}
// This triggers "Uncaught (in promise) Error: API returned 500"
fetchUserData();
The promise from fetchUserData() rejects immediately. Since you didn't attach .catch() or await it, the rejection bubbles up to the global scope, and the browser reports it as unhandled.
How to Fix It
async function fetchUserData() {
throw new Error("API returned 500");
}
// Fix 1: attach .catch()
fetchUserData().catch((error) => {
console.error("Failed to load user:", error.message);
});
// Fix 2: use try/catch with await (inside an async context)
async function handleLoad() {
try {
await fetchUserData();
} catch (error) {
console.error("Failed to load user:", error.message);
}
}
Both fixes work because they consume the rejection. The .catch() method returns a new promise that resolves, so the original rejection is handled. The try/catch does the same thing syntactically — it captures the rejection and lets you respond to it.
Common Mistakes That Cause This
-
Returning a promise from a function without handling it — you write
return fetchData()in a helper, but the caller never awaits or catches it. The helper returns a promise, but nobody consumes it. -
Chaining promises without a final catch — you write
fetchData().then(processData).then(renderUI)but forget the terminal.catch(). Any rejection in the chain becomes unhandled.
When Should You Worry About This?
You should worry immediately if the error appears during user interaction or data loading. An unhandled rejection means your UI could be showing stale data, missing error states, or silently broken features. However, if it happens in a background task like analytics or logging, it's still a bug — fix it before it masks real failures.
What to Check First
Check whether the promise is coming from an event handler or a lifecycle method like useEffect in React — those are the two places where developers most often forget to attach .catch().