DeprecationWarnings in nodejs application - javascript

my user.js
const express=require('express')
const router=express.Router()
const gravatar=require('gravatar')
const bcrypt=require('bcryptjs')
const {check,validationResult} =require('express-validator/check')
const User=require('../../models/User')
//#route POST api/users
//#desc Register user
//#access public
router.post('/',[
check('name','Name is required').not().isEmpty(),
check('email','please include a valid email').isEmail(),
check('password','please enter password with more than 6 characters').isLength({min:6})
],async(req,res)=>{
const errors=validationResult(req);
if(!errors.isEmpty()){
return res.status(400).json({errors:errors.array()})
}
const {name,email,password}=req.body;
try{
//see if the user exists
let user = await User.findOne({ email: email })
//if record exists in DB
if (user) {
return res.status(400).json({ errors: [{ msg: "user already exists" }] });
}
//get users gravatar
const avatar=gravatar.url(email,{
s:'200', //size
r:'pg', //rating of image
d:'mm' //gives a default image
})
user=new User({
name,
email,
avatar,
password
})
//encrpyt password
const salt=await bcrypt.genSalt(10) // 10-no of rounds.more the better
user.password=await bcrypt.hash(password,salt); //coverts to hash pass
await user.save();
//return jsonwebtoken
res.send('User registered')
}catch(e){
console.log(e.message)
res.status(500).send('server error')
}
res.send('User route')
})
module.exports=router;
the app is working fine but in the terminal i get
(node:1022) UnhandledPromiseRejectionWarning: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
at ServerResponse.setHeader (_http_outgoing.js:464:11)
at ServerResponse.header (/Users/udayshetty/Desktop/MERN app/node_modules/express/lib/response.js:771:10)
at ServerResponse.send (/Users/udayshetty/Desktop/MERN app/node_modules/express/lib/response.js:170:12)
at /Users/udayshetty/Desktop/MERN app/routes/api/users.js:60:9
at processTicksAndRejections (internal/process/task_queues.js:85:5)
(node:1022) 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: 1)
(node:1022) [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.

This error occurs when your app is responding to the client over HTTP - and you try to send the response / response headers twice. Once the response is sent, the connection will be closed. You can only send them once for a given http request. You can keep a connection open and send more data , but you cannot send the response headers again.
Please try to remove res.send('User route').
You are sending a response twice.

Related

Check if there is no id in database node.js

so bassically, i am creating a router to update data in database, I started by checking the id in database using if function, at first it works when there is no such id I put in the path, but its come out with this error
BError [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\jansen stanlie\Desktop\simple-app\node_modules\express\lib\response.js:794:10)
at ServerResponse.send (C:\Users\jansen stanlie\Desktop\simple-app\node_modules\express\lib\response.js:174:12)
at ServerResponse.json (C:\Users\jansen stanlie\Desktop\simple-app\node_modules\express\lib\response.js:278:15)
at C:\Users\jansen stanlie\Desktop\simple-app\controllers\todo.controller.js:79:21
at Array.forEach ()
at C:\Users\jansen stanlie\Desktop\simple-app\controllers\todo.controller.js:60:9
at processTicksAndRejections (internal/process/task_queues.js:93:5)
at async putToDo (C:\Users\jansen stanlie\Desktop\simple-app\controllers\todo.controller.js:54:2) {
code: 'ERR_HTTP_HEADERS_SENT'
}
(node:12008) 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\jansen stanlie\Desktop\simple-app\node_modules\express\lib\response.js:794:10)
at ServerResponse.send (C:\Users\jansen stanlie\Desktop\simple-app\node_modules\express\lib\response.js:174:12)
at ServerResponse.json (C:\Users\jansen stanlie\Desktop\simple-app\node_modules\express\lib\response.js:278:15)
at C:\Users\jansen stanlie\Desktop\simple-app\controllers\todo.controller.js:86:20
at processTicksAndRejections (internal/process/task_queues.js:93:5)
at async putToDo (C:\Users\jansen stanlie\Desktop\simple-app\controllers\todo.controller.js:54:2)
(Use node --trace-warnings ... to show where the warning was created)
(node:12008) 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:12008) [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.
and after that I cannot update any data even though there is in the database
here is my code
const putToDo = async (req, res) => {
const body = req.body;
let id = req.params.id;
console.log(id);
let data = [];
let updatedData = [];
await db
.query("select * from suppliers")
.then((results) => {
data = results.rows;
})
.then(() => {
data.forEach((datas) => {
if (datas.id == id) {
db.query(
`UPDATE suppliers
SET Name = '${body.name}'
WHERE id = ${id};`
)
.then(() => {
db.query("select * from suppliers").then((updated) => {
updatedData = updated;
console.log(updatedData);
});
})
.then(() => {
res.status(200).json({
message: "Data Successfully Updated",
});
});
}
res.status(500).json({
message: "No data in database",
});
});
})
.catch((e) => {
console.log(e);
res.status(500).json({
message: "INTERNAL SERVER ERROR",
});
});};
where did I do wrong here...?
The error says you are trying to set headers after already sending a response
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client at
That is because your res.status(500)
res.status(500).json({message: "No data in database"});
Runs after the res.status(200).json()
res.status(200).json({ message: "Data Successfully Updated"})
Try adding an else to your condition so only 1 or the other will execute.
if (datas.id == id) {
db.query(
`UPDATE suppliers
SET Name = '${body.name}'
WHERE id = ${id};`
)
.then(() => {
db.query("select * from suppliers").then((updated) => {
updatedData = updated;
console.log(updatedData);
});
})
.then(() => {
res.status(200).json({
message: "Data Successfully Updated",
});
});
} else {
res.status(500).json({
message: "No data in database",
});
}
Additionally, you are using res.status().json() multiple times within a loop, but should likely only be sending 1 response back that includes all the data instead of a response for every item in the looped data.

How to resolve Unhandled Promise Rejection Warning

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();
},
};
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.
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.

When I send a GET request : Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client

when I tried to send a get request to the url of my function (on a firebase project ex: http://project_url.com/api/post/id), this error shows
(node:1061) UnhandledPromiseRejectionWarning: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
> at ServerResponse.setHeader (_http_outgoing.js:518:11)
> at ServerResponse.header (/Users/salvatorebramante/beta/functions/node_modules/express/lib/response.js:771:10)
> at ServerResponse.send (/Users/salvatorebramante/beta/functions/node_modules/express/lib/response.js:170:12)
> at ServerResponse.json (/Users/salvatorebramante/beta/functions/node_modules/express/lib/response.js:267:15)
> at /Users/salvatorebramante/beta/functions/handlers/posts.js:70:25
> at processTicksAndRejections (internal/process/task_queues.js:97:5)
> (node:1061) 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: 2)
The function returns a json with the infos about a document stored in firebase cloud storage
exports.getPost = (req,res) => {
let postData;
db.doc(`/posts/${req.params.postId}`).get()
.then(doc =>{
if(!doc.exists){
return res.status(404).json({error : 'Post not found'})
}
postData = doc.data();
postData.postId = doc.id;
return db.collection('comments').orderBy('createdAt', 'desc').where('postId','==',req.params.postId).get();
})
.then(data =>{
postId.comments = [];
data.forEach(doc => {
postData.comments.push(doc.data());
})
return res.json(postData);
})
.catch(err =>{
res.status(500).json({ error: err.code });
console.error(err);
});
};
While the error occurred, the get request response is 404, but I've checked that the document id is correct. How can I resolve it?

field in mongoose model is required : true but it is being created in postman

i am trying to give only name in the body and want error in the postman ...but for the status response in postman is 201 created but it is throwing error in console as
UnhandledPromiseRejectionWarning: ValidationError: User validation failed: password: Path password is required., email: Path email is required.
at model.Document.invalidate (C:\projects\MERN\backend\node_modules\mongoose\lib\document.js:2564:32)
at C:\projects\MERN\backend\node_modules\mongoose\lib\document.js:2386:17
at C:\projects\MERN\backend\node_modules\mongoose\lib\schematype.js:1181:9
at processTicksAndRejections (internal/process/task_queues.js:79:11)
(node:6524) 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:6524) [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.
why there is no error in postman???????????
const mongoose = require('mongoose')
const userSchema = new mongoose.Schema({
name:{
type : String,
required : true
},
email:{
type : String,
required : true,
unique:true,
},
password:{
type : String,
required : true,
minlength: 7
},
date:{
type :Date,
default: Date.now
}
})
const User = mongoose.model('User',userSchema)
module.exports = User
router.post("/", async (req, res) => {
try {
const user = await new User(req.body);
user.save();
res.status(201).send({user});
} catch (e) {
res.status(500).send(e);
}
});
consider that your node application throws some error right and crashes as you describe well above. Because your node app is interfacing with the internet you need to devise a way to interpret the error from you app into to an error that is known by the internet also, that way postman will be able to tell that an error has occured...So how do we achieve this, the answer is error handling...
We will use your User model as you have described, and consider the code below it...
router.post("/", async (req, res) => {
try {
const user = await new User(req.body);
// One important thing to note is that the return of this function call below is
// a Promise object which means that it executes asynchrounously and from the error
// log you have above, it is the reason your app is crashing...
user.save();
res.status(201).send({user});
} catch (e) {
res.status(500).send(e);
}
});
So then lets fix it...
router.post("/", async (req, res) => {
const user = await new User(req.body);
return user.save()
// the then call simply accepts a callback that is executed after the async is complete
.then((result) => res.status(201).send({user}))
// this catch will be called in case the call encounters an error during execution
.catch((error) => res.status(500).send(error));
});
Note now we handle the error in the catch by responding to the HTTP request as you have with a 500 code...and also sending the error along with the response

Express "UnhandledPromiseRejectionWarning: RangeError" in login middleware

I'm doing a RESTful API for a vuejs frontend with authentication and data saving by account.
I get this error when trying to log a user in.
Basically my frontend will send a request with a body containing a username and password.
Here's the log in middleware in express :
exports.post_LogIn = (req, res, next) => {
User.findOne({ username: req.body.username })
.then(foundUser => {
if (!foundUser) {
console.log("no user");
const error = new Error("No user with that username");
error.statusCode = 400;
error.tosend = "No user with that username";
throw error;
} else {
return bcrypt.compare(req.body.password, foundUser.password);
}
})
.then(isEqual => {
if (!isEqual) {
console.log("wrong password");
const error = new Error("Passwords don't match");
error.statusCode = 400;
error.tosend = "Passwords don't match";
throw error;
}
console.log("logged in");
const token = jwt.sign(
{
username: foundUser.username
},
"secretpassword",
{ expiresIn: "24h" }
);
console.log(token);
res.status(200).json({ username: foundUser.username });
})
.catch(err => {
res.status(err.statusCode).json({ message: err.tosend });
});
};
So basically when there's a problem with the credentials (either wrong username or password) I wanna send a response to the front end with a message saying what was wrong, and let the front end deal with it.
This works just fine and as expected.
However when I send valid credentials, my console.log statement goes through, but the token and response part gives me this error
(node:14515) UnhandledPromiseRejectionWarning: RangeError
[ERR_HTTP_INVALID_STATUS_CODE]: Invalid status code: undefined
at ServerResponse.writeHead (_http_server.js:242:11)
at ServerResponse._implicitHeader (_http_server.js:233:8)
at write_ (_http_outgoing.js:579:9)
at ServerResponse.end (_http_outgoing.js:689:5)
at ServerResponse.send (/home/martin/dev/projets/trader-backend/node_modules/express/lib/response.js:221:10)
at ServerResponse.json (/home/martin/dev/projets/trader-backend/node_modules/express/lib/response.js:267:15)
at /home/martin/dev/projets/trader-backend/controllers/UserController.js:97:34
(node:14515) 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: 1) (node:14515) [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.
I tried commenting out the token part, or commenting the response and console logging the token, and I still get the same error.
However if I comment out the token and use res.send instead of res.json it seems to be working fine and my front end gets the response.
Any idea what might be causing this ? I'm kind of lost here

Categories