Next.js App Routerでエラー時に500ステータスコードを返せない問題をRoute Groupで解決
はじめに
NextjsのApp Router使用時にしばしば見受けられる問題、throw new Error()をしても500エラーにならない問題とRoute Groupsでの解決方法を取り上げます。
問題の概要
Next.jsのApp Routerでerror.tsxを使用してエラーハンドリングを実装していますが、Server Componentでthrow new Error()をしても、HTTPステータスコードが200 OKのまま、エラーページが表示されてしまいます。
期待される動作
- Server Componentでエラーを投げる
-
error.tsxでエラー画面が表示される - HTTPステータスコードは500 Internal Server Errorが返される
環境
- Nextjs 15.x
- react 19.x
- app router
解決方法
以下の記事によると、Nextのバージョン15.3.4を使用していると500が返せるようです。
バージョンが違うとはいえ同じNext15系ですが、私の環境では再現できませんでした。
私の場合、問題は layout.tsx にありました。
コード例:
export default function Page () {
throw new Error("internal server error occurred")
}
export default function Error () {
return (
<div>internal server error occurred</div>
)
}
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en">
<body>
<Provider>
<Header />
{children}
<Footer />
</ Provider>
</body>
</html>
);
}
どうやら、throw new Errorされた時にlayout.tsxのProvider,Header,Footerが評価され、ステータスが200となっているようです。
しかしchildrenはエラーのため、error.tsxが表示されていました。
試しにProvider,Header,Footerを削除してみます。
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en">
<body>
{children}
</body>
</html>
);
}

うまくいきました。
しかしProvider,Header,Footerを各ページに記述するのは冗長を極めます。
構成の変更
ディレクトリ構成を変更する必要があります。
app/
├── layout.tsx // ← html/bodyのみ
├── error.tsx // ← ここでエラーをキャッチ
├── (main)/
│ ├── layout.tsx // ← Header, Footer, Provider等
│ └── page.tsx
│ └── some-page/
│ └── page.tsx // ← ここでthrow
このようにlayoutを入れ子にすることでerror.tsxが(main)/layout.tsxより外側にあるため、(main)/layout.tsxの評価前にエラーをキャッチできます。
なお、パフォーマンスへの影響はないと考えられます。
なぜこの問題が起きたのかの考察
App Routerはストリーミングレンダリングを採用しており、layout.tsxとページが並列に評価されます。
layout.tsxの出力(<html>タグ等)が先にクライアントに送信されると、その時点でHTTPステータスコード200が確定してしまいます。
HTTPの仕様上、レスポンスボディの送信が始まるとステータスコードは変更できないため、
後からページでエラーが発生しても200のままになったと考えられます。
最後に
ここまでお読みいただきありがとうございました。
今回紹介した方法以外にも解決方法はいくつかあるようです。
- BEまたはAPI Serverでステータスを明示的に返す
- pages routerを使用する
- middlwareを実装する
などです。
ご自身のプロジェクトにあった解決方法をお試しいただければと思います。
よきエンジニアライフを!
Discussion