Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

190
Views
Properly handling exceptions from async functions at the top level

I'm having trouble understanding the correct way to handle exceptions from async functions without triggering Node's UnhandledPromiseRejectionWarning (since that seems to suggest that I'm doing something wrong).

Normally, in non-async code, unhandled exceptions bubble all the way to the top and eventually get printed to the console. The code that resulted in the exception is stopped all the way back up the stack.

Say I have the following code:

test1().catch((e) => { throw e; });
console.log('got here top-level'); // This will print

async function test1() {
    let test2Result = await test2();
    console.log('got here test 1'); // This won't print
    return test2Result;
}

async function test2() {
    throw new Error('something failed here');
}

I would expect that this would do what I want. At the top-most level, it catches the exception from the async functions and re-throws (but now outside any async code or Promises). It should still have the original stack trace so I can find the problem. Happy days, right? But no, this still results in UnhandledPromiseRejectionWarning and I don't understand why.

What's the proper way to catch all unhandled exceptions from inside Promises?

about 4 years ago · Juan Pablo Isaza
2 answers
Answer question

0

Your misunderstanding comes from this statement...

catches the exception from the async functions and re-throws (but now outside any async code or Promises)

Promise.prototype.catch() is still async code. It returns a Promise, just like .then() (in fact, .catch(onRejected) is simply an alias for .then(undefined, onRejected)).

Fun fact, if the .catch() callback doesn't return a rejected promise (eg Promise.reject()) or throw, it returns a successful / resolved promise.

When you throw e within your .catch(), the return value is a rejected Promise and since this is unhandled / uncaught, you get the infamous UnhandledPromiseRejectionWarning.

To avoid it, simply handle all possible promise rejections

test1().catch(console.error); // returns a resolved promise

// or

try {
  await test1();
} catch (e) {
  // consider this handled
}
about 4 years ago · Juan Pablo Isaza Report

0

I generally do something like this:

async function main() {
  // do some async stuff here
  await someAsyncWork();
}

let cc;

main()
.then( () => {
  console.log('success!');
  cc = 0 ;
}
.catch( e => {
  console.error(e.stack);
  cc = 1;
})
.finally( () => process.exit(cc) );
about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!