如何解决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" }); }
错误原因分析
- 重复发送响应:
- GET分支中,
getUser(req, res)应该已经向客户端发送了响应(比如数据库为空时返回空数组),随后又执行res.status(200).json(...),导致两次响应。 - 不管switch分支逻辑如何,函数末尾的
res.status(200).json({ name: "John Doe" })会在所有请求完成后再次发送响应,这是核心问题。
- GET分支中,
- 数据库连接错误未终止后续逻辑:
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`); } }
修复要点说明
- 数据库连接处理:改用try/catch包裹
connectMongo,并在错误时return终止后续代码,避免重复响应。 - 每个分支只发送一次响应:在switch的每个分支中使用return,确保执行完当前分支逻辑后不再执行后续代码;GET分支直接交由
getUser处理响应,移除多余的res.json。 - 移除全局重复响应:删除函数末尾的
res.status(200).json(...),确保每个请求只有一次响应输出。
内容的提问来源于stack exchange,提问作者Kusal Kalinga
相关产品推荐
相关产品推荐

