brand logo

ドキュメント

error.vue

error.vue ファイルは Nuxt アプリケーションのエラーページです。

アプリケーションのライフスパン中に、ランタイムで予期せぬエラーが発生することがあります。そのような場合、error.vue ファイルを使用してデフォルトのエラーファイルを上書きし、エラーをきれいに表示することができます。

error.vue
<script setup lang="ts">
import type { NuxtError } from '#app'

const props = defineProps({
  error: Object as () => NuxtError
})
</script>

<template>
  <div>
    <h1>{{ error.statusCode }}</h1>
    <NuxtLink to="/">Go back home</NuxtLink>
  </div>
</template>

「エラーページ」と呼ばれていますが、これはルートではなく、~/pages ディレクトリに配置すべきではありません。同じ理由で、このページ内で definePageMeta を使用すべきではありません。とはいえ、NuxtLayout コンポーネントを利用してレイアウトの名前を指定することで、エラーファイル内でレイアウトを使用することは可能です。

エラーページには単一のプロップ error があり、これには処理するためのエラーが含まれています。

error オブジェクトは以下のフィールドを提供します:

{
  statusCode: number
  fatal: boolean
  unhandled: boolean
  statusMessage?: string
  data?: unknown
  cause?: unknown
}

カスタムフィールドを持つエラーがある場合、それらは失われます。それらを data に割り当てるべきです:

throw createError({
  statusCode: 404,
  statusMessage: 'Page Not Found',
  data: {
    myCustomField: true
  }
})

tips

このセクションは公式ドキュメントの翻訳ではなく、本サイト独自の補足記事です。

Nuxtのerror.vueで実現するカスタムエラーページのメリット

Nuxtアプリケーションでは、ランタイム中に予期せぬエラーが発生することがあります。そんな時に備えて、error.vue ファイルを用意することで、デフォルトのエラーページを上書きし、ユーザーにわかりやすく美しいエラーページを表示できます。これにより、ユーザー体験の向上やブランドイメージの維持が可能です。

また、エラーの種類や状況に応じて柔軟に表示内容を変えられるため、開発者はエラー処理の一元管理がしやすくなります。特に大規模なアプリケーションでは、エラーの見せ方を統一することが重要です。

まず結論:error.vueのポイント

  • error.vue は Nuxtアプリのエラーページをカスタマイズするための特別なファイル
  • ~/pages 配下に置かず、ルートページとして扱わないことが必須
  • error プロップでエラー情報を受け取り、状態コードやメッセージを表示可能
  • レイアウトは NuxtLayout コンポーネントで指定できる(ただし definePageMeta は使わない)
  • カスタムエラー情報は data フィールドに格納し、画面表示に活用できる

いつ使うべきか、使わない方がよいケース

使うべきケース

  • アプリケーション全体のエラーハンドリングを統一したいとき
  • 404や500などHTTPステータスに応じたカスタムメッセージを表示したいとき
  • ユーザーに対して親切なエラーメッセージやナビゲーションを提供したいとき
  • エラー発生時に特定のレイアウトやスタイルを適用したいとき

使わない方がよいケース

  • ページ単位で細かく異なるエラーハンドリングをしたい場合(個別のtry-catchやエラーハンドラを推奨)
  • エラー内容に応じて動的にコンポーネントを切り替えたいが、複雑すぎるロジックを入れたい場合(error.vueはシンプルな表示に留めるのが望ましい)
  • クライアントサイドのみで完結するエラー処理(例えばフォームのバリデーションエラーなど)は別途コンポーネントで対応したほうが良い

実務でよくあるユースケースとサンプルコード

1. 404ページのカスタマイズ

ユーザーが存在しないページにアクセスした際に、わかりやすいメッセージとホームへのリンクを表示します。

<script setup lang="ts">
const props = defineProps({
  error: Object as () => { statusCode: number; statusMessage?: string }
})
</script>

<template>
  <div class="error-page">
    <h1>{{ error.statusCode }}</h1>
    <p>{{ error.statusMessage || 'ページが見つかりませんでした。' }}</p>
    <NuxtLink to="/">ホームに戻る</NuxtLink>
  </div>
</template>

2. API通信エラー時の表示

APIからのレスポンスエラーを受け取り、ユーザーに適切な説明を表示。data にカスタム情報を入れて活用。

throw createError({
  statusCode: 503,
  statusMessage: 'サービスが一時的に利用できません',
  data: { retryAfter: 30 }
})
<script setup lang="ts">
const props = defineProps({
  error: Object as () => { statusCode: number; statusMessage?: string; data?: { retryAfter?: number } }
})
</script>

<template>
  <div>
    <h1>{{ error.statusCode }}</h1>
    <p>{{ error.statusMessage }}</p>
    <p v-if="error.data?.retryAfter">
      {{ error.data.retryAfter }}秒後に再試行してください。
    </p>
  </div>
</template>

3. レイアウトを指定したエラーページ

共通レイアウトを使いながらエラーページを表示したい場合。

<script setup lang="ts">
const props = defineProps({
  error: Object as () => { statusCode: number }
})
</script>

<template>
  <NuxtLayout name="error-layout">
    <div>
      <h1>エラー {{ error.statusCode }}</h1>
      <NuxtLink to="/">トップへ戻る</NuxtLink>
    </div>
  </NuxtLayout>
</template>

よくある落とし穴・注意点

1. error.vue はページとして扱わない

~/pages 配下に置くとルーティングに影響し、意図しない挙動になります。必ずプロジェクトルートの error.vue として配置してください。

2. definePageMeta は使わない

エラーページはページメタ情報を持たないため、definePageMeta を使うとエラーになるか無視されます。レイアウト指定は NuxtLayout コンポーネントで行いましょう。

3. SSRとHydrationの違いに注意

サーバーサイドレンダリング時にエラーが発生すると、error.vue がサーバーでレンダリングされます。クライアント側でのHydration時に状態が変わると不整合が起きる可能性があるため、エラー情報はできるだけサーバー側で確定させることが望ましいです。

4. パフォーマンスへの影響

エラーページは通常のページよりもシンプルに保つことが推奨されます。複雑なロジックや重いコンポーネントを入れると、エラー発生時のレスポンスが遅くなり、ユーザー体験が悪化します。

まとめ

Nuxtのerror.vueは、アプリケーション全体のエラーハンドリングを統一し、ユーザーにわかりやすいエラーメッセージを提供するための強力な仕組みです。正しく配置し、適切に使うことで、UXの向上や保守性の高いコード設計が可能になります。実務では、404やAPIエラーの表示、レイアウト指定などのユースケースが多く、注意点を押さえれば安全に運用できます。ぜひカスタムエラーページを活用して、より良いNuxtアプリケーションを作りましょう。

エラー情報のカスタムフィールドは必ず data に入れて渡すことで、error.vue 側で安全に扱えます。直接カスタムプロパティを追加すると失われるため注意してください。