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

如何解决Node.js中[ERR_HTTP_HEADERS_SENT]响应头重复发送错误?

解决 [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client 错误

错误场景

发送GET请求到/api/users接口时,终端抛出如下错误,期望数据库为空时返回空数组。

[ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client error

error - Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
    at new NodeError (node:internal/errors:387:5)
    at ServerResponse.setHeader (node:_http_outgoing:644:11)
    at ServerResponse._res.setHeader (D:\Tutorials\CRUD_mongoDB\crud-app-mongodb\node_modules\next\dist\server\base-server.js:129:24)
    at sendJson (D:\Tutorials\CRUD_mongoDB\crud-app-mongodb\node_modules\next\dist\server\api-utils\node.js:195:9)
    at ServerResponse.apiRes.json (D:\Tutorials\CRUD_mongoDB\crud-app-mongodb\node_modules\next\dist\server\api-utils\node.js:351:31)
    at handler (webpack-internal:///(api)/./pages/api/users/index.js:55:21)
    at Object.apiResolver (D:\Tutorials\CRUD_mongoDB\crud-app-mongodb\node_modules\next\dist\server\api-utils\node.js:363:15)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at async DevServer.runApi (D:\Tutorials\CRUD_mongoDB\crud-app-mongodb\node_modules\next\dist\server\next-server.js:487:9)
    at async Object.fn (D:\Tutorials\CRUD_mongoDB\crud-app-mongodb\node_modules\next\dist\server\next-server.js:749:37)
    at async Router.execute (D:\Tutorials\CRUD_mongoDB\crud-app-mongodb\node_modules\next\dist\server\router.js:253:36)
    at async DevServer.run (D:\Tutorials\CRUD_mongoDB\crud-app-mongodb\node_modules\next\dist\server\base-server.js:384:29)
    at async DevServer.run (D:\Tutorials\CRUD_mongoDB\crud-app-mongodb\node_modules\next\dist\server\dev\next-dev-server.js:741:20)
    at async DevServer.handleRequest (D:\Tutorials\CRUD_mongoDB\crud-app-mongodb\node_modules\next\dist\server\base-server.js:322:20) {
  code: 'ERR_HTTP_HEADERS_SENT',
  page: '/api/users'

原接口代码

import connectMongo from "../../../database/conn";
import { getUser } from "../../../database/controller";

export default async function handler(req, res) {
  connectMongo().catch(() =>
    res.status(405).json({ error: "Eoor in the connection" })
  );

  //type of req
  //GET , POST , PUT , DELETE

  const { method } = req;

  switch (method) {
    case "GET":
      getUser(req, res);
      res.status(200).json({ method, name: "GET Req" });
      break;
    case "POST":
      res.status(200).json({ method, name: "POST Req" });
      break;
    case "PUT":
      res.status(200).json({ method, name: "PUT Req" });
      break;
    case "DELETE":
      res.status(200).json({ method, name: "DELETE Req" });
      break;
    default:
      res.setHeader("Allow", ["GET", "POST", "PUT", "DELETE"]);
      res.status(405).end(`Method ${method} Not Allowed`);
      break;
  }

  res.status(200).json({ name: "John Doe" });
}

错误原因分析

  1. 重复发送响应:
    • GET分支中,getUser(req, res)应该已经向客户端发送了响应(比如数据库为空时返回空数组),随后又执行res.status(200).json(...),导致两次响应。
    • 不管switch分支逻辑如何,函数末尾的res.status(200).json({ name: "John Doe" })会在所有请求完成后再次发送响应,这是核心问题。
  2. 数据库连接错误未终止后续逻辑:connectMongo().catch(...)中发送错误响应后没有return,后续代码依然会执行,可能引发重复响应。

修复后的代码

import connectMongo from "../../../database/conn";
import { getUser } from "../../../database/controller";

export default async function handler(req, res) {
  // 连接数据库失败时返回错误并终止后续逻辑
  try {
    await connectMongo();
  } catch (err) {
    return res.status(500).json({ error: "Error in the connection" });
  }

  const { method } = req;

  switch (method) {
    case "GET":
      // 由getUser负责发送响应(空数组或数据列表)
      return getUser(req, res);
    case "POST":
      return res.status(200).json({ method, name: "POST Req" });
    case "PUT":
      return res.status(200).json({ method, name: "PUT Req" });
    case "DELETE":
      return res.status(200).json({ method, name: "DELETE Req" });
    default:
      res.setHeader("Allow", ["GET", "POST", "PUT", "DELETE"]);
      return res.status(405).end(`Method ${method} Not Allowed`);
  }
}

修复要点说明

  1. 数据库连接处理:改用try/catch包裹connectMongo,并在错误时return终止后续代码,避免重复响应。
  2. 每个分支只发送一次响应:在switch的每个分支中使用return,确保执行完当前分支逻辑后不再执行后续代码;GET分支直接交由getUser处理响应,移除多余的res.json。
  3. 移除全局重复响应:删除函数末尾的res.status(200).json(...),确保每个请求只有一次响应输出。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 15:25:22