0
votes

Can anyone explain me the error and give me the solution?

Code is

router.post("/login", (req, res, next) => {
  if(!req.body.email || !req.body.password){
    return res.status(401).json({ success:false, message:'Email or Password Missing' });
  }

  let fetchedUser;

  const isEmailValid = emailPatternMatch(req.body.email);
  if(!isEmailValid){
    return res.status(401).json({ success:false, message:'Email not valid' });
  }

  User.findOne({email: req.body.email})
    .then(user => {
      if (!user){
        return res.status(401).json({ success: false, message:'Email Address is not Registered' });
      }

      fetchedUser = user;
      return bcrypt.compare(req.body.password, user.password);
    })
    .then(result=> {
      if(!result){
        return res.status(401).json({ success: false, message:'Incorrect Password' });
      }
      const token = jwt.sign({ email: fetchedUser.email, userId: fetchedUser._id }, scretKey, { expiresIn: "1h" } );
      return res.status(200).json({ success: true, token: token, userId: fetchedUser._id, expiresIn: 3600 });
    })
    .catch(err => {
      console.log(err);
      return res.status(401).json({ success:false, message: 'Authentication Failed' });
    });
});

Error is

(node:4084) UnhandledPromiseRejectionWarning: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client at ServerResponse.setHeader (_http_outgoing.js:526:11) at ServerResponse.header (C:\Users\umesh\Desktop\Locationist\node_modules\express\lib\response.js:771:10) at ServerResponse.send (C:\Users\umesh\Desktop\Locationist\node_modules\express\lib\response.js:170:12) at ServerResponse.json (C:\Users\umesh\Desktop\Locationist\node_modules\express\lib\response.js:267:15) at C:\Users\umesh\Desktop\Locationist\backend\routes\user.js:82:30 at processTicksAndRejections (internal/process/task_queues.js:97:5) (node:4084) 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:4084) [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.

1
Does this happen in any specific instance? E.g. only when you type in the wrong password or the right password or when the email does not exist in the DB? - abondoa
Your code is somehow calling res.status().json() more than once, which throws an error because a server can't respond to a single browser request more than once. Use console.log(1), 2, 3, 4, to see how far it gets and when it goes bad. You can wrap everything inside your route with a try{}catch{} if you don't really care, or you can refactor your function to use async/await, which will benefit you because you'll be able to predictably return a single response. - TJBlackman

1 Answers

0
votes

I am noticing that in your first then you are calling res.status if the user is not found. In your next then, you will potentially be calling res.status again, which would result in the promise being rejected, since it was already called. In your catch you are again calling res.status, thus rejecting that promise which has no catch around it, leading to an unhandled promise.

To fix this you will need to avoid calling res.status multiple times. Your could e.g. throw an exception in your then and let your catch handle it:

...
User.findOne({email: req.body.email})
    .then(user => {
      if (!user){
        throw { success: false, message:'Email Address is not Registered' };
      }

      fetchedUser = user;
      return bcrypt.compare(req.body.password, user.password);
    })
    .then(result=> {
      if(!result){
        throw { success: false, message:'Incorrect Password' };
      }
      const token = jwt.sign({ email: fetchedUser.email, userId: fetchedUser._id }, scretKey, { expiresIn: "1h" } );
      return res.status(200).json({ success: true, token: token, userId: fetchedUser._id, expiresIn: 3600 });
    })
    .catch(err => {
      console.log(err);
      return res.status(401).json(err);
    });