Node.js: Cannot set headers after they are sent to the client
Express/Node.jsで1リクエストに複数回レスポンスを送ると発生するERR_HTTP_HEADERS_SENTの原因と解決策
概要
Cannot set headers after they are sent to the client は、1つのHTTPリクエストに対してレスポンスを2回以上送信しようとしたときに発生します。HTTPは1リクエストにつき1レスポンスのみで、ヘッダー送信後は変更できないため、res.json() / res.send() / res.end() を重複して呼ぶとこのエラーになります。
エラーメッセージ
現行のNode.js(24 LTS / 22 LTS)およびExpress 5では、ERR_HTTP_HEADERS_SENT コード付きで出力されます。
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
at ServerResponse.setHeader (node:_http_outgoing:699:11)
at ServerResponse.header (/app/node_modules/express/lib/response.js:771:10)
at ServerResponse.send (/app/node_modules/express/lib/response.js:170:12)
at /app/routes/user.js:14:9
旧バージョンでは次の形式で出ることもあります(同じ原因です)。
Error: Can't set headers after they are sent.
原因
- レスポンス送信後の
return忘れ:res.json()の後に処理が続き、もう一度res.send()が呼ばれる(最頻パターン)。 - 非同期処理の二重発火: コールバックと
awaitの両方、あるいは Promise のthenとcatchの両方でレスポンスを送ってしまう。 - ミドルウェアでの送信後に
next(): ミドルウェアがレスポンスを返したのにnext()を呼び、後続ハンドラが再送信する。 - ループ内での送信:
forEach/forの各要素でres.send()を呼んでいる。
解決策
1. レスポンスを送ったら必ず return で打ち切る
| |
return がないと 404 を返した後も res.json(user) に到達し、二重送信になります。
2. res.headersSent で送信済みかチェックする
共通のエラーハンドラなど、複数経路から呼ばれる関数では送信済みフラグを確認します。
| |
3. 非同期エラーはハンドラ内で完結させる(Express 5)
Express 5 では async ハンドラが reject すると自動的にエラーハンドラへ転送されます。try/catch で握りつぶして二重に送らないようにします。
| |
4. ミドルウェアでは「送信」か「next()」のどちらか一方だけ
| |
よくある間違い
ループ内で各要素ごとにレスポンスを送ると、2件目以降でエラーになります。
| |
関連エラー
関連エラー
Node.js の他のエラー
この記事は役に立ちましたか?