You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Express自定义错误类全局异常处理报错求助

Express全局错误处理失效问题

作为Express新手,在使用自定义错误类和中间件做全局错误处理时遇到问题:在控制器中调用next(new AppError())抛出错误后,错误没有进入errorMiddleware,而是直接输出错误栈信息。


自定义错误类 app.error.ts

export class AppError extends Error {
  statusCode: number;
  constructor(message: string, statusCode: number) {
    super(message);
    this.statusCode = statusCode;

    Error.captureStackTrace(this, this.constructor);
  }
}

控制器 chat.controller.ts

export const chat = async (req: Request, res: Response, next: NextFunction) => {
  const { prompt } = req.body;
  if (!prompt) 
      {
         // 此处使用AppError类时出现报错
         return next(new AppError("Prompt is required", 400));
      }

  try {
    // 异步任务...

    const responseText = 'Response Text';

    const response: IResponse<string> = {
      success: true,
      data: responseText,
    };

    return sendResponse(res, response, HttpStatus.OK);
  } catch (error: any) {
    // catch中使用同样出现问题
    return next(new AppError(error.message, 500));
  }
};

报错信息

Error: Prompt is required
    at E:\Projects\vibe-ai\vibe-ai-backend\src\controllers\chat.controller.ts:11:28
    at Generator.next (<anonymous>)
    at E:\Projects\vibe-ai\vibe-ai-backend\src\controllers\chat.controller.ts:8:71
    at new Promise (<anonymous>)
    at __awaiter (E:\Projects\vibe-ai\vibe-ai-backend\src\controllers\chat.controller.ts:4:12)
    at chat (E:\Projects\vibe-ai\vibe-ai-backend\src\controllers\chat.controller.ts:9:79)
    at Layer.handle [as handle_request] (E:\Projects\vibe-ai\vibe-ai-backend\node_modules\express\lib\router\layer.js:95:5)
    at next (E:\Projects\vibe-ai\vibe-ai-backend\node_modules\express\lib\router\route.js:149:13)
    at Route.dispatch (E:\Projects\vibe-ai\vibe-ai-backend\node_modules\express\lib\router\route.js:119:3)
    at Layer.handle [as handle_request] (E:\Projects\vibe-ai\vibe-ai-backend\node_modules\express\lib\router\layer.js:95:5)

主应用配置

import express, { Request, Response, NextFunction } from "express";
import { config } from "dotenv";
import HttpStatus from "http-status-codes";

config();
import { errorMiddleware } from "./src/middlewares";
import { chatRouter } from "./src/routes";
import { AppError } from "./src/utils";

const app = express();
const PORT = process.env.PORT || 6050;

app.use(express.json());
app.use(express.urlencoded({ extended: true }));

app.use(此处为控制器路由);

app.all("*", (req: Request, res: Response, next: NextFunction) => {
  return next(new AppError("Route not found", HttpStatus.NOT_FOUND));
});

app.use(errorMiddleware);

app.listen(PORT, () =>
  console.log(`App is listening at port http://localhost:${PORT}`)
);

错误中间件 error.middleware.ts

const errorMiddleware = (err: AppError, req: Request, res: Response) => {
  err.statusCode = err.statusCode || 500;
  err.message = err.message || SystemConstants.WENT_WRONG;

  const response: IResponse<undefined> = {
    success: false,
    message: err.message,
    stack: err.stack,
  };

  return res.status(err.statusCode).json(response);
};

已尝试操作

  • 在多处添加日志,但错误抛出后未进入错误中间件,仅在AppError类中能看到日志
  • 尝试使用throw new AppError(),但了解到异步场景下该方式无效

问题原因及解决方法

1. 错误中间件参数不完整

Express的错误处理中间件必须包含4个参数:err, req, res, next,缺少next参数会导致Express不识别这是一个错误处理中间件,直接跳过它。

修改error.middleware.ts:

const errorMiddleware = (err: AppError, req: Request, res: Response, next: NextFunction) => {
  err.statusCode = err.statusCode || 500;
  err.message = err.message || SystemConstants.WENT_WRONG;

  const response: IResponse<undefined> = {
    success: false,
    message: err.message,
    stack: err.stack,
  };

  return res.status(err.statusCode).json(response);
};

2. 确认路由注册顺序

确保错误中间件是最后注册的中间件,必须放在所有路由和其他中间件之后。同时检查此处为控制器路由是否正确注册了chatRouter,比如:

app.use('/chat', chatRouter);

3. 验证错误中间件接收情况

在错误中间件开头添加日志,确认是否接收到错误:

const errorMiddleware = (err: AppError, req: Request, res: Response, next: NextFunction) => {
  console.log('进入错误中间件:', err); // 添加日志验证
  err.statusCode = err.statusCode || 500;
  err.message = err.message || SystemConstants.WENT_WRONG;

  const response: IResponse<undefined> = {
    success: false,
    message: err.message,
    stack: err.stack,
  };

  return res.status(err.statusCode).json(response);
};

4. 异步函数错误兜底

如果使用Express 4版本,异步控制器的未捕获错误需要手动传递给next,你当前的try/catch写法是正确的,但要确保所有异步操作都被包裹在try块中。


内容的提问来源于stack exchange,提问作者Varun Savaliya

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 22:30:56