'Error handling when throw an error for user authentication nodejs

I have set up a middleware for error handling:

//errorMiddleware.js
export const notFound = (req, res, next) => {
  const error = new Error(`Not Found - ${req.originalUrl}`);
  res.status(404);
  next(error);
};

export const errorHandler = (err, req, res, next) => {
  res.status(err.status || 500);

  res.json({
    errors: { message: err.message },
  });
};

I try to write API to auth user, for example. When user enter wrong email or password, I throw an error:

const { email, password } = req.body;

  const user = await User.findOne({ email });

  if (user && (await user.comparePassword(password))) {
    res.json({
      _id: user._id,
      name: user.name,
      email: user.email,
      isAdmin: user.isAdmin,
      token: generateToken(user._id),
    });
  } else {
    res.status(401);
    throw new Error("Invalid email or password");
  }

However, I use postman to test request, it's cause an error and not send any response i have set up above:

(node:15900) UnhandledPromiseRejectionWarning: Error: Invalid email or password
    at authUser (file:///D:/Practice%20Web/MERN/eCommerce/backend/controllers/userController.js:20:11)       
    at processTicksAndRejections (internal/process/task_queues.js:95:5)
(Use `node --trace-warnings ...` to show where the warning was created)
(node:15900) 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(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)        
(node:15900) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

How can I handle that problem. Thanks in advance!



Solution 1:[1]

There is a couple of things to understand here.

  1. Async code (await) should be always in the try and catch block, or a parent has the catch block, either way you should always try to catch it somewhere. In order to not have the unhandled error anymore.

  2. The function that is failing / throwing error is the user.comparePassword(password) function. Because you do not have try catch block here, that function throws error and node does not know what to do with it.

  3. Since you have an error handler that takes care of errors in your routes / functions you should try and catch all possible errors and pass it to the next function.

  try {
    if (
      user is not valid
    ) {
      throw new Error('Your error', 401);
    }

    // do some other stuff
    res.json(results)
  } catch (err) {
    next(err);
  }
  1. Please note that you can pass the status number to error, this will get passed to res.status(err.status || 500);
  2. Another thing to remember is to be careful with res.send, once you do this the response is sent and all the other sub res.send calls will result in type error. So you have to make sure that the error handler sends the error for you, not the function you are calling.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1