All posts
javascriptpromisesdebugging

Uncaught (in promise) — What It Means and How to Fix It

"Uncaught (in promise)" explained — why it happens, a real code example that triggers it, and the exact fix.

SR

Suhail Roushan

August 6, 2026

·
3 min read
·
0 views

"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 used await inside a try/catch.
  • Event handler promises — promises created inside onClick, setTimeout, or event listeners that reject without a handler.
  • Async function without try/catch — an async function 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

  1. 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.

  2. 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().

Related posts

Written by Suhail Roushan — Full-stack developer. More posts on AI, Next.js, and building products at suhailroushan.com/blog.

Get in touch