Node.js Express/Mongoose场景下错误处理中间件无法获取控制器抛出错误的完整属性
问题根因
- 错误处理中间件中使用
let error = { ...err }浅拷贝错误对象时,原生Error对象的核心属性(name/message/stack)属于不可枚举属性,对象扩展运算符只会复制可枚举的自有属性,因此拷贝后的对象会丢失这些属性。 - 你当前在控制器的
catch块中,无论捕获到什么错误,都直接封装成了自定义的ErrorResponse实例传给next,如果你的自定义错误类没有正确挂载name属性,也会导致错误处理中间件读取不到该属性。
解决方案
1. 修复错误处理中间件的取值逻辑
不要直接用扩展运算符拷贝错误对象,直接从原始err对象上读取属性即可,修改后的代码如下:
const errorHandler = (err, req, res, next) => { console.log(`Error in method:${req.method}: ${err.stack}`.bgRed); // 直接从原始err取值,避免丢失不可枚举属性 const statusCode = err.statusCode || 500; const message = err.message || 'Server Error'; console.log(`Error handler: ${err.name}`); res.status(statusCode).json({ success: false, data: message, }); }; module.exports = errorHandler;
如果确实需要拷贝错误对象做修改,手动补充不可枚举属性即可:
let error = { ...err, name: err.name, message: err.message, stack: err.stack };
2. 确保自定义ErrorResponse类实现正确
检查你utils/error.js中的ErrorResponse类是否正确继承Error并挂载name属性,标准实现参考:
class ErrorResponse extends Error { constructor(message, statusCode) { super(message); this.statusCode = statusCode; // 手动设置错误类型名 this.name = 'ErrorResponse'; // 保留正确的栈追踪 Error.captureStackTrace(this, this.constructor); } } module.exports = ErrorResponse;
3. 按需保留原始错误信息
如果你需要在错误处理中间件中判断原生错误类型(比如Mongoose的CastError/ValidationError等),不要在catch块中直接把所有错误都封装成ErrorResponse,可以判断错误类型后再处理,保留原始错误的属性:
catch (err) { console.log(err.name); console.log('ERROR APPEND'); // 针对特定错误类型返回自定义提示 if(err.name === 'CastError') { return next(new ErrorResponse(`Product not found with id:${req.params.id}`, 404)); } // 其他错误直接传递,保留原始属性 next(err); }
内容的提问来源于stack exchange,提问作者Muhtar
相关产品推荐
相关产品推荐

