0

I have cretaed a simple signup functionality and added some checks to it which aren't working correctly. They are giving the error :

(node:14256) UnhandledPromiseRejectionWarning: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
    at ServerResponse.setHeader (_http_outgoing.js:558:11)
    at ServerResponse.header (C:\Users\hp\Desktop\Projects\chatapp-backend\node_modules\express\lib\response.js:771:10)
    at ServerResponse.send (C:\Users\hp\Desktop\Projects\chatapp-backend\node_modules\express\lib\response.js:170:12)
    at ServerResponse.json (C:\Users\hp\Desktop\Projects\chatapp-backend\node_modules\express\lib\response.js:267:15)
    at CreateUser (C:\Users\hp\Desktop\Projects\chatapp-backend\controllers\auth.js:29:58)
    at processTicksAndRejections (internal/process/task_queues.js:93:5)
(Use `node --trace-warnings ...` to show where the warning was created)
(node:14256) 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:14256) [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.

According to my expectation while using postman when i enter the same email or username it should give message accordingly but it gives such error

auth.js file:

const Joi=require('joi');
const HttpStatus=require('http-status-codes');
const bcrypt=require('bcryptjs');

const User=require('../models/userModels');
const Helpers=require('../Helpers/helpers');

module.exports={
  async CreateUser(req,res){
    const schema = Joi.object({
      username: Joi.string()
        .min(5)
        .max(10)
        .required(),
      email: Joi.string()
        .email()
        .required(),
      password: Joi.string()
        .min(5)
        .required()
    });

    const validation = schema.validate(req.body);
    res.send(validation);
    console.log(validation);

    const userEmail=await User.findOne({email :(req.body.email)});
    if(userEmail){
      return res.status(HttpStatus.StatusCodes.CONFLICT).json({message: 'Email already exist'});
    }

    const userName=await User.findOne({
      username: (req.body.username)
    });
    if(userName){
      return res.status(HttpStatus.StatusCodes.CONFLICT).json({message: 'Username already exist'});
    }

    return bcrypt.hash(req.body.password,10,(err,hash)=>{
      if(err){
        return res.status(HttpStatus.StatusCodes.BAD_REQUEST).json({message: 'Error hashing password'});
      }

      const body={
        username: Helpers.firstUpper(req.body.username),
        email: Helpers.lowerCase(req.body.email),
        password: hash
      }

      User.create(body).then((user) => {
        res.status(HttpStatus/HttpStatus.StatusCodes.CREATED).json({message: 'USer created successfully',user})
      }).catch(err => {
        res.status(HttpStatus.StatusCodes.INTERNAL_SERVER_ERROR).json({message: 'Error occured'})
      })
    });
}
};

helpers.js file

const User = require('../models/userModels');
module.exports={
  firstUpper: username => {
    const name = username.toLowerCase();
    return name.charAt(0).toUpperCase() + name.slice(1);
  },

  lowerCase: str => {
    return str.toLowerCase();
  },
};
VLAZ
  • 26,331
  • 9
  • 49
  • 67

2 Answers2

0

This is a popular error - "Error: Can't set headers after they are sent." If you are sending data after you have already sent a final request like res.send(), you will see this.

 //Don't send anything to your response after this.
 res.send(validation);
//You have multiple res.status after this, and if any of that runs then you will see this error.
Tushar Shahi
  • 16,452
  • 1
  • 18
  • 39
0

You are trying to send response twice while first is already in transition. I'm not sure why you want to send back the validation to the client but this is causing an issue :

const validation = schema.validate(req.body);
    // return res.send(validation); // or just add this validation to another response 
    console.log(validation);

try {
    
    const userEmail=await User.findOne({email :(req.body.email)});

    if(userEmail){

    return res.status(HttpStatus.StatusCodes.CONFLICT).json({message: 'Email already exist', validation: validation});
    }

    const userName=await User.findOne({
      username: (req.body.username)
    });

    if(userName){
    
    return res.status(HttpStatus.StatusCodes.CONFLICT).json({message: 'Username already exist', validation: validation});
    }
}

catch(console.errror);


Also, when you use async/await use try/catch for error handling. You should check this post to get why this happens and how to avoid it in future.

Apoorva Chikara
  • 8,277
  • 3
  • 20
  • 35