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

233
Views
Node throws unhandled promise rejection while using rejected promise as input parameter

I discovered a weird issue while trying to implement a function that awaits all promises of an array and catches all errors. This implementation led to a complete application crash caused by an unhandled promise rejection.

const completeAllPromises = async (promises) => {
    const errors = []

    for (let i = 0; i < promises.length; i++) {
        await promises[i].catch((error) => {
            error.message = `${i}: ${error.message}`
            errors.push(error)
        })
    }

    if (errors.length) return Promise.reject(errors)
}

const timeout = (duration) => {
    return new Promise((resolve) => setTimeout(() => resolve()), duration)
}

const fail = async () => {
    return Promise.reject(new Error('Failed'))
}

const crash = async () => {
    await completeAllPromises([timeout(100), fail()]).catch(
        (error) => console.log(`Crash prevented, catch promise rejection`, error), // never be called
    )
}

const main = async () => {
    // will crash and catch will not be called
    await crash().catch((error) => console.log('Finished crash() and catch error', error))
}

main()

It seems like the catch implementation in completeAllPromises function is executed at runtime, so while awaiting the first timeout promise, fail() will reject and not be catch. The weird thing for me is that the crash() and also not main() will catch this error. It almost seems like the call chain is not resolvable at the time fail() rejects.

Switching timeout(100) and fail() will result in a properly catch errors. Using a try and catch block will also lead to the same issue.

Solution ✅

const completeAllPromises = async (promises) => {
    const errors = []
    const results = await Promise.allSettled(promises)
    results.forEach((result) => {
        if (result.status === 'rejected') errors.push(result.reason)
    })
    if (errors.length) return Promise.reject(errors)
}

const timeout = (duration) => {
    return new Promise((resolve) => setTimeout(() => resolve()), duration)
}

const fail = async () => {
    return Promise.reject(new Error('Failed'))
}

const crash = async () => {
    await completeAllPromises([timeout(100), fail()]).catch(
        (error) => console.log(`Crash prevented, catch promise rejection`, error), // never be called
    )
}

const main = async () => {
    // will crash and catch will not be called
    await crash().catch((error) => console.log('Finished crash() and catch error', error))
}

main()
about 4 years ago · Juan Pablo Isaza
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!