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

Javascriptnode.jsExpress

Javascript Problem Overview


I am getting following error in my Node-Express App

> UnhandledPromiseRejectionWarning: Unhandled promise rejection. 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(). (rejection id: 4)

To say the least, I have created a helper function which looks something like this

const getEmails = (userID, targettedEndpoint, headerAccessToken) => {
    return axios.get(base_url + userID + targettedEndpoint,  { headers: {"Authorization" : `Bearer ${headerAccessToken}`} })
    .catch(error => { throw error})
}

and then I am importing this helper function

const gmaiLHelper = require("./../helper/gmail_helper")

and calling it inside my api route like this

router.get("/emailfetch", authCheck, async (req, res) => {
  //listing messages in users mailbox 
  let emailFetch = await gmaiLHelper.getEmails(req.user._doc.profile_id , '/messages', req.user.accessToken)
  .catch(error => { throw error})
  emailFetch = emailFetch.data
  res.send(emailFetch)
})

From my end, I think I am handling the error by using catch block.

Question: Can someone explain me why I am getting the error and how can I fix it?

Javascript Solutions


Solution 1 - Javascript

.catch(error => { throw error}) is a no-op. It results in unhandled rejection in route handler.

As explained in this answer, Express doesn't support promises, all rejections should be handled manually:

router.get("/emailfetch", authCheck, async (req, res, next) => {
  try {
  //listing messages in users mailbox 
    let emailFetch = await gmaiLHelper.getEmails(req.user._doc.profile_id , '/messages', req.user.accessToken)
    emailFetch = emailFetch.data
    res.send(emailFetch)
  } catch (err) {
    next(err);
  }
})

Solution 2 - Javascript

I suggest removing the below code from getMails

 .catch(error => { throw error})

In your main function you should put await and related code in Try block and also add one catch block where you failure code.


you function gmaiLHelper.getEmails should return a promise which has reject and resolve in it.

Now while calling and using await put that in try catch block(remove the .catch) as below.

router.get("/emailfetch", authCheck, async (req, res) => {
  //listing messages in users mailbox 
try{
  let emailFetch = await gmaiLHelper.getEmails(req.user._doc.profile_id , '/messages', req.user.accessToken)
}
catch (error) { 
 // your catch block code goes here
})

Solution 3 - Javascript

You are catching the error but then you are re throwing it. You should try and handle it more gracefully, otherwise your user is going to see 500, internal server, errors.

You may want to send back a response telling the user what went wrong as well as logging the error on your server.

I am not sure exactly what errors the request might return, you may want to return something like.

router.get("/emailfetch", authCheck, async (req, res) => {
  try {
    let emailFetch = await gmaiLHelper.getEmails(req.user._doc.profile_id , '/messages', req.user.accessToken)
      emailFetch = emailFetch.data
      res.send(emailFetch)
   } catch(error) {
      res.status(error.response.status)
      return res.send(error.message);
    })

})

This code will need to be adapted to match the errors that you get from the axios call.

I have also converted the code to use the try and catch syntax since you are already using async.

Solution 4 - Javascript

use express-async-errors on your app

like this

app.ts

import 'express-async-errors'

Later,configure your application to read the instance of error.

class Custom Error

class Error{
  
  public readonly message: string;
  public readonly statusCode: number;
  public readonly data?: any

  constructor(message: string, statusCode = 400, data?: any){
    this.message = message;
    this.statusCode = statusCode;
    this.data = data;
  }
}

export default Error

Middleware to use on your app -> app.use(youMiddleware())

import { Request, Response, NextFunction } from 'express'
import AppError from '../errors/AppError'

function globalErrors(err: Error, request: Request, response: Response, next: NextFunction) {

  if (err instanceof AppError) {
    response.status(err.statusCode).json({
      status: 'error',
      message: err.message,
      data: err?.data
    });
  }

  console.error(err);

  return response.status(500).json({
    status: 'error',
    message: 'Internal server error'
  });

}

export { globalErrors };

Solution 5 - Javascript

I resolve the problem. It's very simple . if do you checking care the problem may be because the auxiliar variable has whitespace. Why ? I don't know but yus must use the trim() method and will resolve the problem

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionanny123View Question on Stackoverflow
Solution 1 - JavascriptEstus FlaskView Answer on Stackoverflow
Solution 2 - JavascriptSumerView Answer on Stackoverflow
Solution 3 - JavascripttmcnicolView Answer on Stackoverflow
Solution 4 - JavascriptAntonio Bernardino da SilvaView Answer on Stackoverflow
Solution 5 - JavascriptrjrviudezView Answer on Stackoverflow