Leaderboard
Javascript Jun 28, 2026
Javascript Unhandled Promise Rejection Consequences

JavaScript Promises — What Happens to Unhandled Rejections?

This is a daily Javascript challenge from the CodeShot archive. Practice your knowledge of Unhandled Promise Rejection Consequences and improve your technical interview readiness.

const p = new Promise((_, reject) => reject(new Error("failed")))
// No .catch() attached
A Nothing — they are silently ignored
B UnhandledPromiseRejection warning/error — can crash Node.js processes
C The error is automatically logged to console.error
D The Promise retries automatically

Detailed Explanation

Why This Question Matters

If you've spent any time with JavaScript, you know that Promises are everywhere. But there is a specific kind of frustration that comes with a Promise that fails and doesn't tell you why—or worse, crashes your entire Node.js process.

The "unhandled promise rejection" is one of those weird edge cases that trips up mid-level developers. The confusion usually stems from how JavaScript handles errors. We're used to try...catch blocks for synchronous code, but Promises operate on a different plane. When a Promise rejects and there's no .catch() or await wrapper to pick up the slack, the error doesn't just vanish. It lingers, and depending on your environment, it can lead to silent failures or loud crashes.

Understanding the Code

Let's look at the snippet:

const p = new Promise((_, reject) => reject(new Error("failed")))
// No .catch() attached

Here is what's happening under the hood. We're creating a new Promise. Inside the executor function, we immediately call reject(). This puts the Promise into the rejected state.

Normally, you'd chain a .catch() to this or wrap it in an async function with a try...catch. But in this snippet, we just leave it hanging. The Promise is rejected, but nothing is listening for that failure.

In the early days of Promises, this would often fail silently, which was a nightmare for debugging. You'd see your app stop working, but the console would be empty. Modern engines have changed that, but the behavior still varies between the browser and the server.

Finding the Correct Answer

The correct answer is Option B, which identifies that this results in an unhandledRejection event.

Here is why the other options don't make the cut:

- It doesn't throw a standard synchronous Error: A Promise rejection isn't a typical exception that halts the execution of the current script immediately. It's an asynchronous event. If you put a console.log("Hello") after that Promise declaration, "Hello" would still print.
- It doesn't just "disappear": JavaScript engines are now designed to warn you when you forget to handle a rejection.

When a Promise rejects and no handler is attached, the engine emits a special event. In the browser, you'll see a red error in the console: Uncaught (in promise) Error: failed. In Node.js, it triggers the unhandledRejection event on the process object.

Common Mistakes Developers Make

The biggest mistake I see is the "forgotten catch" in complex chains. You might have a chain of five .then() calls, and you assume the very last .catch() at the bottom will catch everything. While that's generally true, developers often forget that if they create a Promise *inside* another Promise without returning it, the outer catch won't see the inner failure.

Another common trap is mixing async/await with .then(). If you await a function that returns a Promise, you must wrap it in a try...catch. If you don't, and the Promise rejects, it becomes an unhandled rejection.

async function doWork() {
  // If this rejects, and there's no try/catch, 
  // it's an unhandled rejection.
  await someApiCall(); 
}

Real-World Usage

In a production environment, unhandled rejections are dangerous. In older versions of Node.js, they would just print a warning. In newer versions (Node 15+), an unhandled rejection will actually terminate the process with a non-zero exit code. This is a "fail-fast" philosophy: it's better for the app to crash and restart than to continue running in an unstable, unpredictable state.

To prevent your production server from dying unexpectedly, you can implement a global listener. This isn't a replacement for proper .catch() blocks, but it's a great safety net for logging errors to a service like Sentry or LogRocket:

process.on('unhandledRejection', (reason, promise) => {
  console.error('Unhandled Rejection at:', promise, 'reason:', reason);
  // Application-specific logging here
});

Key Takeaways

- A Promise rejection without a .catch() or await wrapper triggers an unhandledRejection event.
- This is not a synchronous error; the rest of your code will keep running until the event loop hits the rejection.
- Browsers log this as an "Uncaught (in promise)" error.
- Node.js will eventually crash your process if you don't handle these rejections.
- Always return your Promises in chains and always use try...catch with async/await.

Why this matters

Understanding Unhandled Promise Rejection Consequences is crucial for passing technical interviews. In real-world applications, this concept often leads to subtle bugs if not handled correctly. For more details, you can always refer to the official MDN Documentation.

📝
Reviewed by CodeShot Editorial
Every challenge is code-reviewed by senior developers to ensure accuracy and real-world relevance. Learn more.

Ready for your shot?

Join thousands of developers solving one logic puzzle every morning.

Solve Today's Challenge →