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

Express应用中调用next(error)后错误中间件未执行问题

Express + TypeScript 错误中间件不执行问题排查

问题场景

使用TypeScript开发Express应用时,在控制器中调用next(error)后,自定义的错误处理中间件并未触发执行,无法捕获并处理抛出的错误。

相关代码

控制器代码

const postCreateUser = async (
    req: Request,
    res: Response,
    next: NextFunction
) => {
    try {
        const { email, username, password, retypePassword } = req.body;
        const isEmailExist = await User.findOne({ where: { email: email } });
        if (isEmailExist) {
            let error: ResponseError = new Error("This email exists");
            error.status = 422;
            next(error);
        }
        const hashedPassword = await bcryptjs.hash(password, 12);
        const user = await User.create({
            username,
            email,
            password: hashedPassword,
        });
        res.status(201).json({ message: "User created succesfully." });
    } catch (err) {
        next(err);
    }
};

错误处理中间件代码

app.use(
    (
        error: ResponseError,
        req: Request,
        res: Response,
        next: NextFunction
    ) => {
        const status = error.status || 500;
        console.log(error);

        res.status(status).json({ message: error.message });
        next();
    }
);

问题原因

  1. 控制器未终止后续代码执行:检测到邮箱已存在并调用next(error)后,没有立即终止函数执行,后续的res.status(201).json(...)仍会发送响应。Express中一旦响应被发送,后续的中间件(包括错误处理中间件)就会被跳过。
  2. 错误中间件挂载位置错误:如果错误中间件被挂载在路由之前,或者部分路由之后、部分路由之前,会导致某些路由的错误无法被捕获。
  3. 错误中间件内多余的next()调用:发送响应后调用next()会尝试将请求传递给下一个中间件,但错误处理中间件通常是最后一个中间件,此时没有后续中间件可处理,反而可能引发不必要的问题。

解决方案

1. 调用next(error)后终止控制器代码

在调用next(error)后添加return,阻止后续代码执行:

if (isEmailExist) {
    let error: ResponseError = new Error("This email exists");
    error.status = 422;
    return next(error); // 添加return终止函数
}

2. 确保错误中间件在所有路由之后挂载

错误处理中间件必须放在所有路由和其他业务中间件的后面,确保所有路由的错误都能被捕获:

// 先注册所有路由
app.use('/api/users', userRoutes);
// 最后挂载错误处理中间件
app.use((error: ResponseError, req: Request, res: Response, next: NextFunction) => {
    const status = error.status || 500;
    console.log(error);
    res.status(status).json({ message: error.message });
    // 移除多余的next()调用
});

3. 移除错误中间件内的next()

错误处理中间件处理完响应后,不需要调用next(),因为此时请求已经完成响应,没有后续中间件需要处理。

内容的提问来源于stack exchange,提问作者Bartosz Chrzanowski

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 15:05:14