生产环境错误处理时isOperational未定义问题求助
问题排查与修复方案
核心问题1:对象展开丢失Error实例的非枚举属性
你在生产环境中用let error = { ...err };复制错误对象,但Error实例的自定义属性(比如你定义的isOperational)属于非枚举属性,对象展开语法只能复制可枚举属性,因此新生成的error对象会丢失isOperational、statusCode这些关键标记。
修复方式:
替换对象展开逻辑,改用Object.assign复制所有属性(包括非枚举属性),同时保留原错误的原型链:
// 替换原有的 { ...err } 代码 let error = Object.assign(Object.create(Object.getPrototypeOf(err)), err);
或者手动补全丢失的核心属性:
let error = { ...err }; // 手动复制非枚举的自定义属性 error.isOperational = err.isOperational; error.statusCode = err.statusCode; error.status = err.status;
核心问题2:CastError的名称判断错误
你代码中判断error.name === 'Cast',但MongoDB抛出的类型错误实际名称是**CastError**,这导致数据库类型错误无法被转换为AppError实例,自然也不会有isOperational属性。
修复方式:
修正判断条件:
if (error.name === 'CastError') error = handleCastErrorDB(error);
修复后的核心代码片段
module.exports = (err, req, res, next) => { err.statusCode = err.statusCode || 500; err.status = err.status || 'error'; if (process.env.NODE_ENV === 'development') { sendErrorDev(err, res); } else if (process.env.NODE_ENV === 'production') { // 正确复制Error实例的所有属性 let error = Object.assign(Object.create(Object.getPrototypeOf(err)), err); if (error.name === 'CastError') error = handleCastErrorDB(error); sendErrorProd(error, res); } next(); };
额外验证提示
确保业务代码中抛出可运行错误时,统一使用new AppError()创建实例,比如:
throw new AppError('Invalid credentials', 401);
只有这样抛出的错误才会自带isOperational: true标记。
内容的提问来源于stack exchange,提问作者Nikhil Raj
相关产品推荐
相关产品推荐

