本文へ移動
verified onnext@16.3.5react@19
最終検証日 2026-09-26
Next.js道場

エラー画面の作り方。error.tsx と global-error

error.tsx は、ページで起きた例外を受け止めて、代わりの画面を出すファイルです。

いちばん小さい形

// app/error.tsx
'use client'
 
export default function Error({
  error,
  retry,
}: {
  error: Error & { digest?: string }
  retry: () => void
}) {
  return (
    <div>
      <p>表示できませんでした。時間をおいてもう一度お試しください。</p>
      <p>{`エラー番号: ${error.digest ?? '-'}`}</p>
      <button onClick={() => retry()}>もう一度読み込む</button>
    </div>
  )
}

'use client' が要ります。付けないとビルドが止まります(この問題)。

retry は、公式ドキュメントによると、中身を読み込み直して描き直す関数です。Next.js 16.3 で安定版になり、以前からある reset より推奨されています。16.3.5 の型にはどちらもあります。

本番では、本当の文言は届かない

データベースにつながらなかった、のような例外の文言をそのまま画面に出したくなります。本番でページが例外を投げたときに、何が見えるかを確かめました。

ページが例外を投げたとき、本番で見えるもの(実機で確かめた)
見る場所出たもの
error.tsx の error.messageMinified React error #441 …(決まった文言)
error.tsx の error.digest番号(例: 2288897430)
ブラウザのコンソールMinified React error #441 …(決まった文言)
サーバーのログthrow した本当の文言と、同じ digest

本当の文言は、サーバーのログにしか出ませんでした。例外の文言には接続先やパスワードのような秘密が入ることがあるので、本番ではブラウザへ送らない作りです。

公式ドキュメントによると、Client Component で起きた例外は元の文言のまま届きます。置き換わるのは、サーバーで起きた例外です。

どの error.tsx が受け止めるか

error.tsx は、同じ階層の page を包む位置に入ります。同じ階層の layout は包みません。

例外が起きた場所と、出た画面(実機で確かめた)
例外が起きた場所出た画面
app/shop/page.tsxapp/shop/error.tsx
app/shop/layout.tsxapp/error.tsx(ひとつ上)
app/layout.tsx(ルート)app/global-error.tsx
app/layout.tsx で、global-error.tsx が無いNext.js の既定の画面(英語)
layout の例外は、ひとつ上へ上がる
  1. Server
    app/shop/layout.tsx が例外を投げる

    app/shop/error.tsx はこの layout の内側にある。

  2. Server
    内側の error.tsx には届かない

    例外は外側へ上がる。

  3. Browser
    app/error.tsx が出る

    shop の画面ではなく、全体のエラー画面になる。

layout でデータを読むと、その失敗で画面全体のエラー画面になります。失敗しうる読み込みは、できるだけ page の側に置いてください。

ルートの layout には global-error.tsx

ルートの layout が例外を投げると、app/error.tsx には届きません。受け止めるのは app/global-error.tsx です。

// app/global-error.tsx
'use client'
 
export default function GlobalError({ retry }: { retry: () => void }) {
  return (
    <html lang="ja">
      <body>
        <p>ただいま表示できません。</p>
        <button onClick={() => retry()}>もう一度読み込む</button>
      </body>
    </html>
  )
}

ルートの layout の代わりに描かれるので、html と body を自分で書きます。公式ドキュメントによると、アプリ全体の CSS やフォントも入らないので、必要なものはこの中で用意します。

置かなかったときは、実機では Next.js の既定の画面が出ました。英語で「This page couldn't load」と、エラーの番号だけが表示されます。

例外にしないほうがよいもの

公式ドキュメントは、起こりうると分かっている失敗(入力の誤りなど)は例外として投げず、値として返して画面に出すよう勧めています。error.tsx は、想定していなかった失敗の最後の受け皿です。

また公式ドキュメントによると、ボタンを押したときの処理(イベントハンドラ)の中で起きた例外は、error.tsx では受け止められません。描いている最中の例外だけが対象です。イベントハンドラの中では自分で try で受けて、画面に出します。

見つからないページは、例外ではなく notFound() で not-found.tsx を出します(見つからないときの最小構成)。

出す前に確かめること

  1. 本番と同じビルドで、わざと例外を投げて、エラー画面が出るかを見る
  2. 画面の digest と、サーバーのログの digest が同じ番号かを見る
  3. ルートの layout でデータを読んでいるなら、global-error.tsx があるかを見る

出典

このページの内容は上記の一次情報を基準に書いています。個人ブログや二次情報を根拠にしていません。

理解できたか試す

では、このコードはどうなりますか。

データベースの失敗を画面に出したくて、error.tsx で error.message を表示しています。本番で、このページが例外を投げました。画面に出る error.message は何ですか。

この問題を解くこのテーマの問題 5 問