Node local server stops instantly as the code does throw err; - node.js

So, in this piece of code I'm trying to use findOne to find and delete a particular dishId from my Favorites document. The code is working fine if I send a valid dishId but when I enter a wrong dishId the code does throw err; and the Node server stops with this error.
events.js:292
throw er; // Unhandled 'error' event
^
TypeError: Cannot read property 'dishes' of null
And then I've to do npm start again. So how should I tackle this? I don't want server to stop. I want it to keep going so that I can do further requests. Here's my code.
favoriteRouter.route('/:dishId')
.delete(cors.corsWithOptions, authenticate.verifyUser, (req,res,next) => {
Favorites.findOne({user: req.user._id, dishes: req.params.dishId} ,(err, favdel) => {
if(err) {
throw err;
}
else {
favdel.dishes.pull({_id:req.params.dishId});
favdel.save();
res.statusCode = 200;
res.setHeader('Content-Type', 'application/json');
res.json(favdel);
}
})
});

The error is pretty clear: you're blindly accessing a property without first checking whether it exists, so: check if favdel.dishes exists before you try to get data out of it. And if it doesn't, make error handling kick in, in a way that makes sure to send the correct HTTP error code.
...
if (!favdel || !favdel.dishes) {
// only you know which 4xx or even 5xx error this should be
return next(new Error("..."));
}
favdel.dishes.pull({_id:req.params.dishId});
favdel.save();
res.statusCode = 200;
res.setHeader('Content-Type', 'application/json');
res.json(favdel);
...

Related

How to catch error in NodeJS and send own error code?

how can I catch an error in NodeJS or create own error code and send it to the frontend to inform the user?
In the following code I am looking into the database result if there were any data deleted and try to send an error code. How can I send the error code to my react frontend? Maybe using response.json("Not deleted any user"). Tried it already out.
How can I prevent my server from crashing? If the sql is not correcting because there was no id send to delete it is crashing.
Thanks for the answers for this two cases.
db.getConnection((err, connection) => {
if (err) throw err;
connection.query(
"DELETE FROM users where users_id = ?",
[2],
(err, rows) => {
connection.release();
if (rows.affectedRows == 0) {
throw err;
}
if (err) throw err;
if (!err) {
res.redirect("/");
} else {
console.log(err);
}
console.log("Daten gelöscht", rows.affectedRows);
}
);
});
You should use a try, catch block. If you want to throw a custom exception, you can do something like
throw new NotFoundException("Record with the given id Not Found...!!!"):
I use it in nestjs I am not fully sure that this will work for you but you can try :)

sequelize handling rejection in the create statement - catch not firing

The sequelize create statement has an error and I would like to handle that error. Since the create statement has the error I need to handle promise rejection. How do I do that in code? Tried to look at the sequelize documents but unable to work it out.
db.Employee.create(empData,
{
include:[
{
model: db.EmployeeDetails
}
]
}).then(function(newEmployee){
res.json(newEmployee);
}).catch(function(err){
return next(err);
});
The error is on the create and so the webpage just gives an internal server error. I was under the impression that the catch was something that handled the promise rejection and failure. In this case, how can I handle the promise rejection in code. An example would be greatly appreciated.
By doing next(err), by default, you send a 500 Internal Server Error message. If you use Express, and want to show a custom error, just append a status code which is not 5xx to the error:
General Usage:
const err = new Error("my custom error")
err.statusCode = 400
next(err)
In your snippet, do:
db.Employee.create(empData, {
include:[
{
model: db.EmployeeDetails
}
]
}).then(function(newEmployee){
res.json(newEmployee);
}).catch(function(err){
err.statusCode = 400
next(err);
});
If you haven't set your error handler in Express you will need to add somewhere at the end of the main file this:
// Error Handler
app.use(function(err, req, res, next) {
console.error(err)
if (!err.statusCode) err.statusCode = 500;
let msg = err.message
// Do not expose 500 error messages in production, to the client
if (process.env.NODE_ENV === "production" && err.statusCode === 500) {
msg = "Internal Server Error"
}
res.status(err.statusCode).send(msg)
})
Your webpage showing a 500 error means the issue was caught / working as intended. What you need to do is figure out how to handle displaying that error in a pretty format - this being a UI task. If you want a 'patch' for hiding the issue, change your return to a res. This will trick your browser with a 200 status and hide the error.
I do want to add, I recommend trying async/await for sequelize. There's a good amount of usage examples with it.
Promise
db.Employee.create(empData,
{
include:[
{
model: db.EmployeeDetails
}
]
}).then(function(newEmployee){
res.json(newEmployee);
}).catch(function(err){
// Temporary patch
res.json("pretty error message");
});
Async/Await version
async function createEmployee(empData) {
try {
return await db.Employee.create(empData, {
include:[ { model: db.EmployeeDetails } ]
});
} catch (err) {
// Handle error here
return err;
}
}

'throw' from within bsync.compare crashes node?

I'm sure this is a novice question, but I've only been having a go at learning express/node/react for a month or so now.
I'm just trying to make a simple node signin REST API call. Here's a snippet of code, with some 'pseudo-izing' of the unimportant parts for brevity:
server.post('/signin', (request, response) => {
const {user_email, password} = request.body
// query db for user validation
db('user_login')
/* knex query building, blah blah blah */
.then(res => {
if (res.length == 0) {
// if res.length == 0, user not found
throw new Error("bad credentials")
} else if (res.length > 1) {
// if res.length > 1, duplicate user found - shouldn't ever happen
throw new Error("CRITICAL: database error")
} else {
// everything should be ok - pass res on to bcrypt
return res
}
})
.then(res => {
// bcrypt.compare doesn't return a promise because it is being given a cb
bcrypt.compare(password, res[0].pw_hash, (err, match) => {
if (match) {
// delete pw_hash from any possible response(),
// don't give client more info than it needs
delete res[0].pw_hash
// we have a match! inform the client
response.json(res[0])
} else {
// we don't have a match
throw new Error("bad credentials") // WHY DOES THIS THROW CRASH!??!?!!?!?
}
})
})
// WHY ISNT THIS REACHED WHEN THERE'S A PASSWORD MISMATCH?
.catch(err => {
console.error('signin error: ', err)
response.status(403).json({
name: err.message,
severity: 'auth error',
code: 403
})
})
})
Ok so:
- When a correct username and correct password is supplied, it functions as expected.
- When an incorrect username is supplied, the .catch is reached (ie. functions as expected).
- BUT: when a correct username and an incorrect password is supplied, the throw statement (with the comment // WHY DOES THIS THROW CRASH?)... crashes node.
Here's the call stack:
C:\.............\server.js:83
throw new Error("bad credentials") // WHY DOES THIS THROW CRASH!??!?!!?!?
^
Error: bad credentials
at C:\.............\server.js:83:23
at C:\.............\node_modules\bcrypt-nodejs\bCrypt.js:689:3
at processTicksAndRejections (internal/process/task_queues.js:75:11)
[nodemon] app crashed - waiting for file changes before starting...
I could "cheat" and just do a response.status(403).... instead of that throw. But in my mind, throwing that error ought to jump to the .catch, and handle any auth failure there.
Can anyone help me w/ what's going on here? It's very frustrating.
PS. This crash only seems to be happening when the throw is within the bcrypt.compare callback. I figure that has something to do with it. I've googled.. I've looked around on here.. I've wrapped things in try/catch blocks. I'm just beating my head against it at this point.
Thank you! :)
Do not throw an error from Node like this. You notice that the bcrypt callback has an err parameter. Send that back and handle it how you want to in the back or front.

Unhandled 'error' event when trowing error

I have the following function for creating an user in my app, I'm trying to detect if threre's already an admin user created and prevent for creating another one.
export async function createUser (ctx) {
if ( ctx.request.body.type == undefined ) {
ctx.throw(400, 'Bad Request')
}
if (ctx.request.body.type === 'admin') {
User.findOne({type:'admin'}, (err, usr) => {
if (err)
ctx.throw(422, err.message)
if (usr){
ctx.throw(400, 'Duplicate Admin')
}
})
}
....
The first ctx.throw(400, 'Bad Request') works, but if another admin user is found the ctx.throw(400, 'Duplicate Admin') will cause the following error, crashing the app:
events.js:160
throw er; // Unhandled 'error' event
^
BadRequestError: Duplicate Admin
I'm throwing the error in an inadequate manner? what causes the first throw to work without crashing but not the second?
Thanks in advance for any help
You're throwing asynchronously inside the User.findOne callback. This crashes.
Instead, look at the library you're using that gives you User.findOne and see if it can return a promise, or wrap it in bluebird's Promise.promisify if it doesn't.
This is the code you want to arrive at:
const user = await User.findOne({ type: 'admin' }) // returns a promise
if (user) ctx.throw(400, 'Duplicate admin')
At first, check the type of 'user' variable.If it an array or object, if(user){....} will always return true, even if it's empty. And try to add
app.on('error', function() {
console.log('yep this is an error');
});
event listener

Nodejs Using domain.dispose() causes server to respond with status 0

When I use domain.dispose() in Node.js expressjs based HTTP Server, the client making HTTP sees a response code of 0 (Could not get any response). If I remove domain.dispose() I receive 500 error with the desired error message. Below is my code
//Enable domains
app.use(function(req, res, next){
var createDomain = require('domain').create;
var domain = createDomain();
domain.add(req);
domain.add(res);
domain.run(function() {
next();
});
domain.on('error', function(e) {
//no further domain watch required
domain.dispose(); //if I remove this line status code of 500 is received on client, otherwise 0 or no response is received
next(e);
});
});
//Respond with 500 for Unhandled errors
app.use(function(err, req, res, next) {
// If the error object doesn't exists
if (!err) return next();
// Log it
req.log.error(err);
//console.error(err.stack);
try{
if(req.path && req.path.indexOf('/api/') === 0){
if(!res.headersSent){
console.log('responded with an error');
res.status(500).send({error: err.message});
console.log('responded with an error ACK');
}
return;
}
// Error page
res.status(500).render('500', {
error: err.stack
});
} catch(ex){
console.log('An error occured while responding 500');
req.log.error(ex);
}
});
Can anyone explain this or a better solution? Removing domain.dispose() may cause further exceptions, which may cause to re-enter the domain, and I do want to acknowledge client with the exception message as in my code.
This is expected behaviour of domains. Since you have explicitly added req and res to domain, so they are disposed as well. Don't use dispose, it does unexpected things. When you catch an error with domain the only sensible thing to do is to shutdown the process as quickly as possible.

Resources