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

Express错误处理中间件未返回预期404错误,求解决方案

解决Mongoose查询无结果时错误处理中间件进入default分支的问题

问题场景

用Mongoose操作数据库,通过express-async-handler处理异步逻辑,搭配自定义errorHandler中间件捕获异常。当查询不到目标文档时,控制器里设置res.status(404)并抛出错误,但errorHandler始终走到default分支,无法返回预期的404错误响应。

控制器代码:

const asyncHandler = require('express-async-handler');
const Contact = require('../models/contactModel');

const getContact = asyncHandler(async (req, res) => {
  const contact = await Contact.findById(req.params.id);

  if (!contact) {
    res.status(404);
    throw new Error('Contact not found');
  }

  res.status(200).json(contact);
});

错误处理中间件代码:

const { constants } = require('../constants');
const errorHandler = (err, req, res, next) => {
  const statusCode = res.statusCode ? res.statusCode : 500;

  switch (statusCode) {
    case constants.VALIDATION_ERROR:
      res.json({
        title: 'Validation failed',
        message: err.message,
        stackTrace: err.stack
      });
    case constants.UNAUTHORIZED:
      res.json({
        title: 'Unauthorized',
        message: err.message,
        stackTrace: err.stack
      });
    case constants.FORBIDDEN:
      res.json({
        title: 'Forbidden',
        message: err.message,
        stackTrace: err.stack
      });
    case constants.NOT_FOUND:
      res.json({
        title: 'Not found',
        message: err.message,
        stackTrace: err.stack
      });
    case constants.SERVER_ERROR:
      res.json({
        title: 'Server error',
        message: err.message,
        stackTrace: err.stack
      });
    default:
      console.log('No error, all is well !');
      break;
  }
};

问题原因

  1. Switch Case未加break:每个case执行完后没有break语句,代码会继续向下遍历,哪怕匹配到了constants.NOT_FOUND,最终还是会走到default分支。
  2. 常量值不匹配:要确认constants文件里的NOT_FOUND数值是不是404,如果和控制器里res.status(404)设置的状态码不一致,也无法匹配对应case。

解决方案

1. 给每个Switch Case添加Break

在每个case的响应逻辑后加上break,确保匹配到对应case后终止switch执行:

const { constants } = require('../constants');
const errorHandler = (err, req, res, next) => {
  const statusCode = res.statusCode ? res.statusCode : 500;

  switch (statusCode) {
    case constants.VALIDATION_ERROR:
      res.json({
        title: 'Validation failed',
        message: err.message,
        stackTrace: err.stack
      });
      break; // 添加break
    case constants.UNAUTHORIZED:
      res.json({
        title: 'Unauthorized',
        message: err.message,
        stackTrace: err.stack
      });
      break; // 添加break
    case constants.FORBIDDEN:
      res.json({
        title: 'Forbidden',
        message: err.message,
        stackTrace: err.stack
      });
      break; // 添加break
    case constants.NOT_FOUND:
      res.json({
        title: 'Not found',
        message: err.message,
        stackTrace: err.stack
      });
      break; // 添加break
    case constants.SERVER_ERROR:
      res.json({
        title: 'Server error',
        message: err.message,
        stackTrace: err.stack
      });
      break; // 添加break
    default:
      console.log('No error, all is well !');
      break;
  }
};

2. 验证常量定义

检查constants.js文件,确保NOT_FOUND的数值为404:

// constants.js
exports.constants = {
  VALIDATION_ERROR: 400,
  UNAUTHORIZED: 401,
  FORBIDDEN: 403,
  NOT_FOUND: 404, // 确认此值为404
  SERVER_ERROR: 500
};

3. 可选:显式设置响应状态码

为了让前端能准确收到状态码,建议在每个case里显式设置响应的状态码(虽控制器已设置,但显式操作更稳妥):

case constants.NOT_FOUND:
  res.status(statusCode).json({
    title: 'Not found',
    message: err.message,
    stackTrace: err.stack
  });
  break;

验证效果

修改完成后,当查询不到文档时,控制器设置404状态码并抛错,errorHandler会正确匹配NOT_FOUND分支,返回对应错误响应,不会再进入default分支。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 20:45:31