I'm trying to authenticate users when registering on my app using Nodejs, express and mongoDB.
The user gets registered successfully and added to my database but then I get this error in the console that .catch is not a function. Which is after my user has been successfully registered and password hashed successfully as well.
what is the cause of the error that makes my server to crash?
console error:
.catch((err) => {
TypeError: res.status(...).send(...).catch is not a function
My code:
bcrypt.hash(req.body.password, 10)
.then((hashedPassword) => {
const user = new User({
email: req.body.email,
password: hashedPassword,
});
user.save().then((result) => {
res.status(201)
.send({
message: "User created successfully",
result,
}).catch((err) => {
// error is pointing at this line of code
res.status(500).send({
message: "Error creating User",
err,
});
});
});
}).catch((err) => {
res.status(500).send({
message: "Password was not hashed successfully",
err,
});
});
});
You placed/copied the catch to the wrong place, it should be catching the error when creating the user not when you send.
So change:
user.save().then((result) => {
res.status(201).send({
message: "User created successfully",
result,
}).catch((err) => {
// error is pointing at this line of code
res.status(500).send({
message: "Error creating User",
err,
});
});
});
to
user.save().then((result) => {
res.status(201).send({
message: "User created successfully",
result,
})
}).catch((err) => {
res.status(500).send({
message: "Error creating User",
err,
});
});
A few aolutions
1.Check your catch() function
You can try to make the code become clearer such as using a try catch function as the code maybe have some problems.
2. If problem #1 didn't work
Re-install express(if the problem didn't solve)
npm install express
Related
this will be a simple answer, but I have this code, that validates if a record exists in the database, and It does, and I got a status 500 from the API call, but keeps creating the duplicate record in my table.
exports.createBet = async (req, res)=>{
betBody = req.body;
newBalance = 0.0;
Bet.findOne({
where: {
[Op.and]: [
{match_id: betBody.matchId},
{user_id: betBody.userId}
]
}
}).then(data=>{
if(data){
return res.status(500).send({message: "Bet already made for this match"});
}
})
.catch(err=>{
return res.status(500).send({ message: "Error creation the bet: " + err.message});
});
balnce = await User.findOne({
where:{
id: betBody.userId
}
})
.then(data=>{
if(data.balance < betBody.betAmount){
return res.status(500).send({ message: "Not enough balance to make that bet."});
}
return data.balance;
})
.catch(err=>{
return res.status(500).send({ message : "Error getting the user in the bet creation: " + err.message})
});
Bet.create({
match_id: betBody.matchId,
bet_amount: betBody.betAmount,
selected_winner: betBody.teamSelect,
user_id: betBody.userId
})
.then(data=>{
res.json(data)
})
.catch(err=>{
return res.status(500).send({ message: "Error creating the bet: " + err.message})
});
newBalance = balnce - betBody.betAmount;
User.update(
{ balance: newBalance},
{ where: {id: betBody.userId}}
)
.catch(err=>{
res.status(500).send({ message: "Error getting user: " + err.message})
});
};
Here it is the response of the api call
And here it is the duplicated records in my table
You should use the promise chain(or async/await correctly) to solve this issue, When a request reaches to createBet function every database call(without await one) is executing parallel, it creates a new record while checking for the existing one.
NOTE: Sometimes You might get a response already sent error. res.send does not stop execution it'll return the response but the remaining code will still execute.
exports.createBet = async (req, res) => {
betBody = req.body;
newBalance = 0.0;
try {
const bet = await Bet.findOne({
where: {
[Op.and]: [{ match_id: betBody.matchId }, { user_id: betBody.userId }],
},
}).catch((err) => {
throw { message: "Error creation the bet: " + err.message };
});
if (bet) {
throw { message: "Bet already made for this match" };
}
//... handle the cases like above, must use await
} catch (err) {
res.status(500).json({ message: err.message });
}
};
This problem causes in your database a saved record without all the fields trying to truncate your table and start a fresh,
I think here in your query all time finds a record(data) thats why we are facing this type of error
If it's not work try to debug your code with log your data which comes from your findOne query
validateRegister: async (req, res, next) => {
UserModel.findOne({email:req.body.email}, (err, example) => {
console.log(example);
if(err) console.log(err);
if(example) {
res.status(400).json({message: "Email already registered!"});
res.end() //next('route')
}
});
console.log("test");
const user = new UserModel(req.body);
await user.save((err) => {
if (err) return res.status(500).json({ message: "Database issue!" });
});
next();
},
Ok, I tried to insert user data if it is not already in the database using mongoose. If the User regarding the email is already in the database the response should be ended and the user not inserted. I tried to end the response with res.end() and next('route'), but nothing seems to work, the console.log("test") still runs.
Error:
events.js:353
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:561:11)
Thanks for your help
Code below callback function gets executed before callback gets completed and multiple res.send happened.
you can try this
validateRegister: async (req, res, next) => {
UserModel.findOne({ email: req.body.email }, (err, example) => {
console.log(example);
if (err) {
console.log(err);
return res.status(500).json({ message: "Something went wrong" });
}
if (example) {
return res.status(400).json({ message: "Email already registered!" });
}
console.log("test");
const user = new UserModel(req.body);
await user.save((err) => {
if (err) return res.status(500).json({ message: "Database issue!" });
});
});
next();
}
Or
validateRegister: async (req, res, next) => {
try {
let example = await UserModel.findOne({ email: req.body.email });
console.log(example);
if (example)
return res.status(400).json({ message: "Email already registered!" });
console.log("test");
const user = new UserModel(req.body);
await user.save((err) => {
if (err) return res.status(500).json({ message: "Database issue!" });
});
next();
} catch (err) {
console.log(err);
return res.status(500).json({ message: "Something went wrong" });
}
}
you can add return before returning response in the case of user email already found.
What seems to happen is that your program is calling res two times
I'm implementing user authentication in my Node REST API.
I have defined in the UserController a method to remove a user:
async function remove(req, res) {
try {
User.findOneAndRemove({ _id: req.params.id });
return res.status(200).json({
message: 'user deleted',
});
} catch (err) {
console.log(err);
res.status(500).json({
error: err,
});
}
}
When I hit the route in Postman with an id from a user stored in the database, I get the success message: "user deleted"
However when I look in the database, the user is still there.
What am I doing wrong?
thanks for your help!
dough, forgot to put 'await' before User.findOneAndRemove ...
I was testing my app on localhost and everything seemed to work correctly, but then I pushed my website to azure websites and things were working there as well except when I create a user it throws 500 error I don't get what could be the possible reason.
here is my route for creating users
router.post('/create', admin, (req, res, next) => {
bcrypt.hash(req.body.password, 10).then(hash => {
const user = new User({
email: req.body.email,
username: req.body.username,
userType: req.body.userType,
company: req.body.company
});
User.countDocuments({
email: req.body.email
})
.then(count => {
if (!count) {
user.save()
.then(result => {
res.status(201).json({
message: 'User created!',
result: result
});
})
.catch(err => {
res.status(500).json({
error: err
});
});
} else {
res.status(500).json({
message: 'Email already exists!'
});
}
})
.catch(err => {
res.status(500).json({
error: err,
message: 'Email already exists!'
});
});
});
});
so whenever I test the app on angular it shows email already exists! and 500 error
My REST API reasons this: {"error":"Auth failed. User does not exist"}.
I try save this error to my state using setState in React, but I have a this error: Cannot read property 'error' of undefined. What's the problem?
export const login = user =>
axios
.post('http://localhost:3000/api/users/login', {
login: user.login,
password: user.password,
})
.then(res => {
localStorage.setItem('userToken', res.data.token);
return res.data.token;
})
.catch(err => {
console.log(err);
});
Function in React.js:
onSubmit(e) {
e.preventDefault();
const user = {
login: this.state.login,
password: this.state.password,
};
login(user).then(res => {
if (!res.error) { // <- this error: TypeError: Cannot read property 'error' of undefined
this.props.history.push(`/dashboard`);
} else {
this.setState({ error: res.error });
}
});
}
This is my backend code:
// Login Action
...
return res.status(200).json({
message: 'Auth successful',
token,
});
}
res
.status(400)
.json({ error: 'Auth failed. The password is incorrect.' });
} else {
res.status(400).json({ error: 'Auth failed. User does not exist' });
}
})
.catch(err => {
res.status(400).json({ error: err });
});
};
Try this:
login(user).then(() => this.props.history.push(`/dashboard`))
.catch(error=>this.setState({ error })
But maybe there is another problem, you cannot normally push to state the way you do for immutability concern. I guess you know, but I post in case:
this.setState({ history: [...this.state.history, `/dashboard`] })
since your backend is returning a response with 400 status code, you have to handle that in the catch block of your login function. right now you are writing the error into the console and not returning anything, that is why your login response is undefined in your React code and you are getting that error.
to fix this, change the catch block of your login function so it looks something like this
.catch(err => {
console.log(err);
return {error:err};
});
Try this;
export const login = user =>
axios
.post('http://localhost:3000/api/users/login', {
login: user.login,
password: user.password,
})
.then(res => {
localStorage.setItem('userToken', res.data.token);
})
.then(() => return localStorage.getItem('userToken');)
.catch(err => {
console.log(err);
});