I'm following a tutorial in the net. It's a MERN project with mongo/mongoose. When I have implemented the update function in the controller the following error has occured :
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
I've seen the answers about similar issue where they say it's because there are 2 or multiple calls of res (res.json(), res.send() etc..), but I don't see where must I change this in the following function :
module.exports.updateUser = async(req, res) => {
if (!ObjectID.isValid(req.params.id))
return res.status(400).send("ID unknown : " + req.params.id);
try {
await UserModel.findOneAndUpdate({
_id: req.params.id
}, {
$set: {
bio: req.body.bio
}
},
(err, docs) => {
if (!err)
return res.send(docs);
if (err)
return res.status(500).send({ message: err });
}
)
} catch (err) {
return res.status(500).json({ message: err });
}
};
It may be that you've mixed up two different error handling patterns.
You don't need try/catch if you're using built in error handling of findOneAndUpdate()
await UserModel.findOneAndUpdate({
_id: req.params.id
}, {
$set: {
bio: req.body.bio
}
},
(err, docs) => {
if (!err)
return res.send(docs);
if (err)
return res.status(500).send({ message: err });
}
)
and if you are using try/catch, you don't need findOneAndUpdate's error handling:
try {
const user = await UserModel.findOneAndUpdate({
_id: req.params.id
}, {
$set: {
bio: req.body.bio
}
})
return res.send(user)
} catch (err) {
return res.status(500).json({ message: err });
}
Could you please change code like this:
module.exports.updateUser = async(req, res) => {
if (!ObjectID.isValid(req.params.id))
return res.status(400).send("ID unknown : " + req.params.id);
try {
const result = await UserModel.findOneAndUpdate({
_id: req.params.id
}, {
$set: {
bio: req.body.bio
}
});
return res.send(result);
} catch (err) {
return res.status(500).json({ message: err });
}
};
I learn mongoose on NodeJS and I wanted to use usefindOneAndUpdate, it works on db I have the updates but the response gives an error and I couldn't find why help me pls.
code:
await userModel.findOneAndUpdate(
{ _id: req.params.id },
{
$set: {
nickName: req.body.nickName,
},
},
{ upsert: true, new: true, setDefaultsOnInsert: true },
(err, docs) => {
if (!err) return res.send(docs);
else return res.status(500).send({ message: err });
}
);
} catch (err) {
return res.status(500).json({ message: err });
}
error:
"originalStack": "Error\n at model.Query._wrappedThunk [as _findOneAndUpdate]
(C:\\Users\\alike\\Documents\\projetsJS\\chatApp-Node-React\\node_modules\\mongoose\\lib\\helpers\\query\\wrapThunk.js:25:28)
at C:\\Users\\alike\\Documents\\projetsJS\\chatApp-Node-React\\node_modules\\kareem\\index.js:279:20
at _next (C:\\Users\\alike\\Documents\\projetsJS\\chatApp-Node-React\\node_modules\\kareem\\index.js:103:16)
at C:\\Users\\alike\\Documents\\projetsJS\\chatApp-Node-React\\node_modules\\kareem\\index.js:508:38
at processTicksAndRejections (internal/process/task_queues.js:77:11)"
Edit: #GulshanAggarwal here is all the file https://i.stack.imgur.com/r4LCj.png
hope you spent really good holidays
I'm following a tutorial online but i've an error that the teacher doesn't have in the video (i also copy his code but same error).
I have this error only with the "PUT" function but the strange thing is that it updates well in mongoDB. It just gives me an error.
Here's my code:
user.controller.js
const UserModel = require("../models/user.model");
const ObjectID = require("mongoose").Types.ObjectId;
module.exports.getAllUsers = async (req, res) => {
const users = await UserModel.find().select("-password");
res.status(200).json(users);
};
module.exports.userInfo = (req, res) => {
if (!ObjectID.isValid(req.params.id))
return res.status(400).send("ID unknown : " + req.params.id);
UserModel.findById(req.params.id, (err, docs) => {
if (!err) res.send(docs);
else console.log("Id unknown" + err);
}).select("-password");
};
module.exports.updateUser = async (req, res) => {
if (!ObjectID.isValid(req.params.id))
return res.status(400).send("ID unknown : " + req.params.id);
try {
await UserModel.findOneAndUpdate(
{ _id: req.params.id },
{
$set: {
bio: req.body.bio,
},
},
{ new: true, upsert: true, setDefaultsOnInsert: true },
(err, docs) => {
if (!err) return res.send(docs);
if (err) return res.status(500).send({ message: err });
}
);
} catch (err) {
return res.status(500).json({ message: err });
}
};
module.exports.deleteUser = async (req, res) => {
if (!ObjectID.isValid(req.params.id))
return res.status(400).send("ID unknown : " + req.params.id);
try {
await UserModel.remove({ _id: req.params.id }).exec();
res.status(200).json({ message: "Successfully deleted. " });
} catch (err) {
return res.status(500).json({ message: err });
}
};
user.model.js :
const mongoose = require("mongoose");
const { isEmail } = require("validator");
const bcrypt = require("bcrypt");
const userSchema = new mongoose.Schema(
{
pseudo: {
type: String,
required: true,
minlength: 3,
maxlength: 55,
unique: true,
trim: true,
},
email: {
type: String,
required: true,
validate: [isEmail],
lowercase: true,
trim: true,
},
password: {
type: String,
required: true,
max: 1024,
minlength: 6,
},
picture: {
type: String,
default: "./upload/profil/random-user.png",
},
bio: {
type: String,
max: 1024,
},
followers: {
type: [String],
},
following: {
type: [String],
},
likes: {
type: [String],
},
},
{
timestamps: true,
}
);
// playfunction before save into db
userSchema.pre("save", async function (next) {
const salt = await bcrypt.genSalt();
this.password = await bcrypt.hash(this.password, salt);
next();
});
// Export user
const UserModel = mongoose.model("user", userSchema);
module.exports = UserModel;
Here the error in terminal:
(node:16752) [MONGODB DRIVER] Warning: collection.remove is deprecated. Use deleteOne, deleteMany, or bulkWrite instead. (Use `node --trace-warnings ...` to show where the warning was created) events.js:292
throw er; // Unhandled 'error' event
^
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 (D:\Programmation\mern\node_modules\express\lib\response.js:771:10)
at ServerResponse.send (D:\Programmation\mern\node_modules\express\lib\response.js:170:12)
at ServerResponse.json (D:\Programmation\mern\node_modules\express\lib\response.js:267:15)
at ServerResponse.send (D:\Programmation\mern\node_modules\express\lib\response.js:158:21)
at D:\Programmation\mern\controllers\user.controller.js:33:30
at D:\Programmation\mern\node_modules\mongoose\lib\model.js:4912:18
at processTicksAndRejections (internal/process/task_queues.js:75:11) Emitted 'error' event on Function instance at:
at D:\Programmation\mern\node_modules\mongoose\lib\model.js:4914:15
at processTicksAndRejections (internal/process/task_queues.js:75:11) { code: 'ERR_HTTP_HEADERS_SENT' }
And here the error in PostMan:
(for information, if i put a wrong id in postman i've my error as expected "ID unknown:" ...)
{
"message": {
"originalStack": "Error\n at model.Query._wrappedThunk [as _findOneAndUpdate] (D:\\Programmation\\mern\\node_modules\\mongoose\\lib\\helpers\\query\\wrapThunk.js:25:28)\n at D:\\Programmation\\mern\\node_modules\\kareem\\index.js:279:20\n at _next (D:\\Programmation\\mern\\node_modules\\kareem\\index.js:103:16)\n at D:\\Programmation\\mern\\node_modules\\kareem\\index.js:508:38\n at processTicksAndRejections (internal/process/task_queues.js:75:11)"
}
}
Earlier i change :
catch (err) {
return res.status(500).json({ message: err });
}"
to a simple
console.log(err)
And had this error in the terminal(but not in Postman anymore):
MongooseError: Query was already executed: user.findOneAndUpdate({ _id: new ObjectId("61363178c0b345e93...
at model.Query._wrappedThunk [as _findOneAndUpdate] (D:\Programmation\mern\node_modules\mongoose\lib\helpers\query\wrapThunk.js:21:19)
at D:\Programmation\mern\node_modules\kareem\index.js:279:20
at _next (D:\Programmation\mern\node_modules\kareem\index.js:103:16)
at D:\Programmation\mern\node_modules\kareem\index.js:508:38
at processTicksAndRejections (internal/process/task_queues.js:75:11) {
originalStack: 'Error\n' +
' at model.Query._wrappedThunk [as _findOneAndUpdate] (D:\\Programmation\\mern\\node_modules\\mongoose\\lib\\helpers\\query\\wrapThunk.js:25:28)\n' +
' at D:\\Programmation\\mern\\node_modules\\kareem\\index.js:279:20\n' +
' at _next (D:\\Programmation\\mern\\node_modules\\kareem\\index.js:103:16)\n' +
' at D:\\Programmation\\mern\\node_modules\\kareem\\index.js:508:38\n' +
' at processTicksAndRejections (internal/process/task_queues.js:75:11)'
}
Thank you in advance for your help !
Have a good day :)
EDIT: After the 1st answer from mohammad Naimi:
I add else, and i still have the same issue, mongodb is actually update but i've the error message
here's my updated code
const UserModel = require("../models/user.model");
const ObjectID = require("mongoose").Types.ObjectId;
module.exports.getAllUsers = async (req, res) => {
const users = await UserModel.find().select("-password");
res.status(200).json(users);
};
module.exports.userInfo = (req, res) => {
if (!ObjectID.isValid(req.params.id))
return res.status(400).send("ID unknown : " + req.params.id);
else {
UserModel.findById(req.params.id, (error, docs) => {
if (!error) res.send(docs);
else console.log("Id unknown" + error);
}).select("-password");
}
};
module.exports.updateUser = async (req, res) => {
if (!ObjectID.isValid(req.params.id))
return res.status(400).send("ID unknown : " + req.params.id);
else {
try {
await UserModel.findOneAndUpdate(
{ _id: req.params.id },
{
$set: {
bio: req.body.bio,
},
},
{ new: true, upsert: true, setDefaultsOnInsert: true },
(error, docs) => {
if (!error) return res.send(docs);
else {
return res.status(500).send({ message: error });
}
}
);
} catch (error) {
return res.status(500).json({ message: error });
}
}
};
module.exports.deleteUser = async (req, res) => {
if (!ObjectID.isValid(req.params.id))
return res.status(400).send("ID unknown : " + req.params.id);
else {
try {
await UserModel.remove({ _id: req.params.id }).exec();
res.status(200).json({ message: "Successfully deleted. " });
} catch (error) {
return res.status(500).json({ message: error });
}
}
};
1st solution: Downgrade your Mongoose version (to 5.10.13 for exemple)
2nd solution: Don't use the callback function, use a .then instead (with Mongoose 6.0.13) :
module.exports.updateUser = async (req, res) => {
if (!ObjectID.isValid(req.params.id))
return res.status(400).send("ID invalid : " + req.params.id);
try {
await UserModel.findOneAndUpdate(
{ _id: req.params.id },
{
$set: {
bio: req.body.bio,
},
},
{ new: true, upsert: true, setDefaultsOnInsert: true }
)
.then((docs) => res.send(docs))
.catch((err) => res.status(500).send({ message: err }));
} catch (err) {
res.status(500).json({ message: err });
}
};
Ok, so after multiple try and fails ! here's the answer : Use mongoose#5.10.6 and it should be good
Have an awesome day coder buddies
I also experienced the same problem but what I erased the callback functions and instead I used the (then) instead of the callback functions
exports.likePost = async (req, res) => {
if (!objectID.isValid(req.params.id))
return res.status(400).send("ID unkonwn:" + req.params.id);
try {
// update for collection post
await postModel.findByIdAndUpdate(
req.params.id,
{
$addToSet: { likers: req.body.id }
},
{ new: true }
// update for colletcion users
).then(async (resp) => {
await userModel.findOneAndUpdate(
req.body.id,
{ $addToSet: { likes: req.params.id } },
{ new: true }
).then(data => {
return res.status(201).json({ message: 'inserted with success' })
});
});
} catch (error) {
return res.status(400).send(error)
}
}
Ok, so after multiple try and fails ! here's the answer : Use mongoose#5.10.6 and it should be good
Have an awesome day coder buddies
Use "mongoose#5.10.6" and your programm will work
I also had the same error but after several searches, I found that instead of a callback function you have to use
.then((docs) => res.send(docs))
I'm updating a model inside an if condition but model not updating
exports.check_verification = (req, res) => {
var verifyCode=req.body.code;
console.log(vcode);
if(verifyCode=vcode){
const veryfy=User.updateOne({ _id:req.body.user_id }, { $set: { verify_status:"Registered"} },)
Promise.all([veryfy]).then(() => {
res.send("success");
}).catch((err) =>{
console.log(err);
})
}else{
console.log("fail");
res.send("fail");
}}
throw an error like this:
According to the error message req.body.user_id is not a string but instead is an object holding:
{ code: '...', user_id: '...' }
So what you can do is :
User.updateOne({ _id:req.body.user_id.user_id } //...
There might be something wrong with your request-model though.
I'm using mongoose Model.findOneAndupdate() to find and update my document and there is a post hook on my model schema for which i'm trying to update another document.
The issue i'm facing is post hook is being triggered twice.
My model:
const mongoose = require('mongoose')
const componentSchema = new mongoose.Schema({
name: {
type: String,
required: true
},
component: {
type: String,
required: true
},
message: {
type: String
},
bodyJson: {
type: mongoose.Schema.Types.Mixed
},
question: {
type: String
}
})
componentSchema.post('findOneAndUpdate', function (result) {
console.log('came here')
})
module.exports = mongoose.model('Component', componentSchema)
In my server log i see that came here logged is twice.
update:
try {
await Component.findOneAndUpdate(query, req.body, { new: true }, function (error, doc) {
if (doc) {
return res.status(200).json({ data: doc })
} else if (error) {
return res.status(400).json({ errors: error.message })
} else res.status(404).json({ errors: 'Not found' })
})
} catch (error) {
logger.error('error while updating order: ' + error)
return res.status(400).json({ errors: error.message })
}
moongoose version i'm using is 5.8.11
You are using both await and callback at the same time. This causes the middleware trigger 2 times. Only one of them must be used.
Use either callback:
Component.findOneAndUpdate(query, req.body, { new: true }, function(
error,
doc
) {
if (err) {
return res.status(400).json({ errors: error.message }); //500 status code may be better
} else {
if (doc) {
return res.status(200).json({ data: doc });
} else {
res.status(404).json({ errors: "Not found" });
}
}
});
Or await:
try {
const doc = await Component.findOneAndUpdate(query, req.body, { new: true });
if (doc) {
return res.status(200).json({ data: doc });
} else {
res.status(404).json({ errors: "Not found" });
}
} catch (error) {
logger.error("error while updating order: " + error);
return res.status(400).json({ errors: error.message });
}