UnhandledPromiseRejection: This error originated either by throwing inside of an async function without a catch block

avatar
Borislav Hadzhiev

Last updated: Mar 7, 2024
7 min

banner

# UnhandledPromiseRejection: This error originated either by throwing inside of an async function without a catch block

The error "UnhandledPromiseRejection: This error originated either by throwing inside of an async function without a catch block or by rejecting a promise which was not handled with .catch()" occurs for multiple reasons:

  1. A rejected promise in an async function without a catch block.
  2. Rejecting a promise which was not handled with a .catch().
  3. Raising an error in a catch() function.

unhandledpromiserejection this error originated either by throwing

shell
node:internal/process/promises:289 triggerUncaughtException(err, true /* fromPromise */); ^ [UnhandledPromiseRejection: This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). The promise rejected with the reason "An error occurred".] { code: 'ERR_UNHANDLED_REJECTION' }

Here is an example of how the error occurs.

index.js
const p = new Promise((resolve, reject) => { return reject('An error occurred'); }); // โ›”๏ธ [UnhandledPromiseRejection: This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). The promise rejected with the reason "An error occurred".] {code: 'ERR_UNHANDLED_REJECTION'} p.then((data) => { console.log('.then block ran: ', data); });
The promise gets rejected and has a .then() function but doesn't have a .catch() function.

We can add a .catch() function to handle the error.

index.js
const p = new Promise((resolve, reject) => { return reject('An error occurred'); }); p.then((data) => { console.log('.then block ran: ', data); }).catch(err => { // ๐Ÿ‘‡๏ธ .catch block ran: An error occurred console.log('.catch block ran: ', err); });

add catch function to handle the error

The .catch() function got called with the error and handled the rejected Promise.

We called the then() function on the promise object to resolve the promise.

The function we passed to the then() method gets called with the resolved value as a parameter. We can access this value in the body of the method.

Notice that we also used the catch() method.

This is necessary because a promise can have 3 states:

  1. pending - initial state, neither fulfilled nor rejected.
  2. fulfilled - the operation was successful and the promise is resolved.
  3. rejected - operation failed.
The function we passed to the then method will get called if the promise is fulfilled and the operation is successful.

If the promise is rejected, we can access the reason (error) for the rejection in the catch() method.

Here is an example of using the resolve() function to resolve the Promise and run the then() function instead.

index.js
const p = new Promise((resolve, reject) => { return resolve('Success message'); }); p.then(data => { // ๐Ÿ‘‡๏ธ .then block ran: Success message console.log('.then block ran: ', data); }).catch(err => { console.log('.catch block ran: ', err); });

We called the resolve() function, so the .then() function got called with the resolved value as a parameter.

# Don't use await in async functions without a try/catch statement

Another common cause of the error is having a rejected promise in an async function without a catch block.

Here is an example.

index.js
async function doWork() { const p = new Promise((resolve, reject) => { return reject('An error occurred'); }); const data = await p; console.log('data is: ', data); } // โ›”๏ธ [UnhandledPromiseRejection: This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). The promise rejected with the reason "An error occurred".] {code: 'ERR_UNHANDLED_REJECTION'} doWork();
We have an async function in which a Promise is rejected, but there is no try/catch statement to handle the rejected promise.

To solve the error, we have to wrap the await statement in a try block, so if an error is raised, it gets passed to the catch() function.

index.js
async function doWork() { const p = new Promise((resolve, reject) => { return reject('An error occurred'); }); try { const data = await p; console.log('data is: ', data); } catch (err) { // ๐Ÿ‘‡๏ธ catch block ran: An error occurred console.log('catch block ran: ', err); } } doWork();

wrap await statement in try block

We await the Promise in the try block but it gets rejected, so the catch() function is called.

The catch function gets passed the error (rejection reason) and handles the error.

This way we don't get an unhandled promise rejection error.

The result of awaiting the promise is the resolved value if the operation was successful.

The await operator is used to wait for a Promise to be fulfilled or rejected.

An easy way to think about it is - when the await operator is used, our code in the particular function stops on the line where await was used until the promise was fulfilled or rejected.

Here is an example of using the resolve() function to demonstrate the success case.

index.js
async function doWork() { const p = new Promise((resolve, reject) => { return resolve('Success message'); }); try { const data = await p; // ๐Ÿ‘‡๏ธ data is: Success message console.log('data is: ', data); } catch (err) { console.log('catch block ran: ', err); } } doWork();

using resolve function to demonstrate the success case

We await the Promise, it gets resolved with the string 'Success message' and the string gets assigned to the data variable.

Using the async/await syntax makes your code more predictable and easier to read than using .then() and .catch().

# Make sure you haven't raised an error in your .catch() function

If you raise an error in your .catch() function without handling it, the Unhandled Promise Rejection error occurs.

Here is an example.

index.js
async function doWork() { const p = new Promise((resolve, reject) => { return reject('First error'); }); try { const data = await p; console.log('data is: ', data); } catch (err) { console.log('catch block ran: ', err); // ๐Ÿ‘‡๏ธ this raises an error throw new Error('An error occurred in catch'); } } // โ›”๏ธ catch block ran: First error // โ›”๏ธ Error: An error occurred in catch doWork();

We await the Promise in the try block and it gets rejected.

The catch() function gets called with the error and handles it, but then it raises another error that isn't handled.

The second error is the reason for the Unhandled Promise Rejection error.

There is no code in our application that handles the second error that occurred in our catch() function.

Make sure you don't have any code that might raise an error in your catch() functions.

# If you have to await an individual promise, wrap it in an IIFE

IIFE (immediately invoked function expressions) can be used to wrap a promise without it being connected to other code in any way, e.g. configuration or database connection initialization code.

index.js
const p = new Promise((resolve, reject) => { return reject('An error occurred'); }); (async function () { try { const data = await p; console.log(data); } catch (err) { // ๐Ÿ‘‡๏ธ Catch block ran: An error occurred console.log('Catch block ran: ', err); } })();

We wrapped an async function in an immediately invoked function expression.

The promise that we awaited got rejected, so the rejection reason got passed to the catch() function.

Had we just awaited the promise without a catch() function, we would have gotten the error.

index.js
const p = new Promise((resolve, reject) => { return reject('An error occurred'); }); // โ›”๏ธ [UnhandledPromiseRejection: This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). The promise rejected with the reason "An error occurred".] {code: 'ERR_UNHANDLED_REJECTION'} (async function () { const data = await p; console.log(data); })();

# Make sure your .catch() function is connected to your .then() function

Here is another example of how the error occurs.

index.js
const p = new Promise((resolve, reject) => { return reject('An error occurred'); }); p.then(data => { console.log('data is: ', data); }); // โ›”๏ธ [UnhandledPromiseRejection: This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). The promise rejected with the reason "An error occurred".] { code: 'ERR_UNHANDLED_REJECTION' } p.catch(err => { console.log('err is: ', err); });

We have a .catch() function but it isn't connected to the .then() function call.

To solve the error, we have to chain the .catch() call after the .then() call.

index.js
const p = new Promise((resolve, reject) => { return reject('An error occurred'); }); p.then(data => { console.log('data is: ', data); }).catch(err => { // ๐Ÿ‘‡๏ธ err is: An error occurred console.log('err is: ', err); });

You might also see examples online that use the second parameter of the .then() function instead of using .catch().

index.js
const p = new Promise((resolve, reject) => { return reject('An error occurred'); }); p.then( data => { console.log('data is: ', data); }, err => { // ๐Ÿ‘‡๏ธ err is: An error occurred console.log('err is: ', err); }, );

The code sample is similar to using .then() and .catch().

You can imagine that the second function we passed to .then() gets treated like a .catch() function and gets called with the rejection reason.

However, you should generally stick to using .catch() because it is more readable and intuitive.

# Conclusion

To solve the error "UnhandledPromiseRejection: This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch()", make sure:

  1. You don't have a rejected promise in an async function without a catch block.
  2. You aren't rejecting a promise which wasn't handled with a .catch().
  3. You aren't raising an error in a catch() function.

# Additional Resources

You can learn more about the related topics by checking out the following tutorials:

I wrote a book in which I share everything I know about how to become a better, more efficient programmer.
book cover
You can use the search field on my Home Page to filter through all of my articles.

Copyright ยฉ 2024 Borislav Hadzhiev