I am trying to implement express error handling middleware. It is working but I don't understand why I have to set error.message
equal to the err.message
after I copy err
to error
. Is the spread operator not copying all the attributes from err
? When I inspect the err object I don't even see a message or a stack attribute. Also, why is it able to log the error message before the error message is created in the if block.
This is how I am extending the Error
// src/utils/errorResponse.js
class ErrorResponse extends Error {
constructor(message, statusCode) {
super(message)
this.statusCode = statusCode
}
}
module.exports = ErrorResponse
Custom error handler middleware
// src/middleware/error.js
const ErrorResponse = require('../utils/errorResponse')
const errorHandler = (err, req, res, next) => {
let error = { ...err }
console.log({ error.message }) // undefined
error.message = err.message
console.log({ error.message }) // `Resource not found with id of ${err.value}`
// Log to console for dev
// console.log(error.stack)
// Mongoose bad ObjectId
if (err.name === 'CastError') {
const message = `Resource not found with id of ${err.value}`
error = new ErrorResponse(message, 404)
} else {
console.log(error.name)
}
res.status(error.statusCode || 500).json({
success: false,
error: error.message || 'Server Error',
})
}
module.exports = errorHandler
I trigger the error by making a get request with a bad ObjectID
// src/controllers/bootcamp.js
const Bootcamp = require('../models/Bootcamp')
...
// @desc Get single bootcamp
// @route GET /api/v1/bootcamps/:id
// @access Public
exports.getBootcamp = async (req, res, next) => {
try {
const bootcamp = await Bootcamp.findById(req.params.id)
if (!bootcamp) {
return next(err)
}
res.status(200).json({ success: true, data: bootcamp })
} catch (err) {
next(err)
}
}
This is happening because the err
parameter you're getting is of Error type object and message key is present in prototype of Error object and spread operator shallow copies keys of object ( excluding prototype keys )
Statement for spread operator from mdn -
The Rest/Spread Properties for ECMAScript proposal (ES2018) added spread properties to object literals. It copies own enumerable properties from a provided object onto a new object.
Shallow-cloning (excluding prototype)
or merging of objects is now possible using a shorter syntax than Object.assign().
For reference -
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax