I need to handle errors in my API server on node.js. I created a error handling module, which sends the errors (only in dev mode) to the API client in a JSON object similar to this:
{
"status": "fail",
"error": {
"statusCode": 404,
"status": "fail",
"isOperational": true
},
"message": "no valid register found. Please provide a valid register",
"stack": "Error: no valid register found. Please provide a valid register\n at /Users/myUser/ITstuff/smarthome-heating/controllers/modbusController.js:77:21\n at async /Users/myUser/ITstuff/smarthome-heating/controllers/modbusController.js:73:17"
}
now the problem I have is, that I need to create a new error in a submodule of my API controller when no case is true in the switch statement.
// this is the modbusHandler.setValue(doc, val, next) function
// 2) RUN PROGRAMMS
let checkVal;
switch (doc.register) {
case 0:
await client.writeCoil(doc.address + offset, !!val);
checkVal = await client.readCoils(doc.address + offset, 1);
break;
case 4:
await client.writeRegister(doc.address + offset, val);
checkVal = await client.readHoldingRegisters(doc.address + offset, 1);
break;
default:
throw new Error(
'no valid register found. Please provide a valid register'
);
}
At this time, I handle it in this way:
// the function is wrapped in a try-catch statement
const val = await modbusHandler.setValue(doc, req.body.value, next).catch((err) => {
console.log('here it is');
return next(new AppError(err.message, 404));
});
res.status(200).json({
status: 'success',
data: {
val,
},
});
- In the API controller, the function with the switch statement gets called
- If no case matches the expression, then it throws a new Error
- catch the error then call the custom error and respond error in a JSON format to the client
This solution works not really, I get a response error because there is no return for the function of the API controller. This causes a second response which is of course not good.
My question is now: How can I solve this problem in the right way?
Custom Error constructor:
class AppError extends Error {
constructor(message, statusCode) {
// this is the official error message rom the error it self, this message will be in the response.json for the client
super(message);
this.statusCode = statusCode;
this.status = `${statusCode}`.startsWith('4') ? 'fail' : 'error';
this.isOperational = true;
Error.captureStackTrace(this, this.constructor);
}
}
module.exports = AppError;
Custom Error handler:
module.exports = (err, req, res, next) => {
err.statusCode = err.statusCode || 500;
err.status = err.status || 'error';
if (process.env.NODE_ENV === 'development') {
sendErrDev(err, res);
} else if (process.env.NODE_ENV === 'production') {
sendErrProd(err, res);
}
};
const sendErrDev = (err, res) => {
res.status(err.statusCode).json({
status: err.status,
error: err,
message: err.message,
stack: err.stack,
});
};