Обработка ошибок

Как перехватывать и обрабатывать ошибки в Nuxt.

Nuxt — full-stack фреймворк, поэтому неизбежные ошибки времени выполнения могут возникать в разных контекстах:

  • Ошибки в жизненном цикле рендеринга Vue (SSR и CSR)
  • Ошибки при запуске сервера и клиента (SSR и CSR)
  • Ошибки в жизненном цикле Nitro-сервера (директория server/)
  • Ошибки загрузки JS-чанков
SSR — Server-Side Rendering (серверный рендеринг), CSR — Client-Side Rendering (клиентский рендеринг).

Ошибки Vue

Перехват ошибок Vue — через onErrorCaptured.

Nuxt также предоставляет хук vue:error, вызываемый при ошибках, дошедших до верхнего уровня.

Для отправки ошибок во внешний сервис задайте глобальный обработчик в vueApp.config.errorHandler. Он получит все ошибки Vue, в том числе уже обработанные.

plugins/error-handler.ts
export default defineNuxtPlugin((nuxtApp) => {
  nuxtApp.vueApp.config.errorHandler = (error, instance, info) => {
    // обработка ошибки, например отправка в сервис
  }

  nuxtApp.hook('vue:error', (error, instance, info) => {
    // обработка ошибки, например отправка в сервис
  })
})
Хук vue:error основан на жизненном цикле onErrorCaptured.

Ошибки при запуске

Nuxt вызовет хук app:error, если при запуске приложения возникла ошибка.

Сюда входят:

  • выполнение плагинов Nuxt
  • обработка хуков app:created и app:beforeMount
  • рендеринг Vue-приложения в HTML (SSR)
  • монтирование приложения на клиенте (этот случай лучше обрабатывать через onErrorCaptured или vue:error)
  • обработка хука app:mounted

Ошибки Nitro-сервера

Отдельный серверный обработчик для этих ошибок сейчас задать нельзя; можно отобразить страницу ошибки — см. раздел «Страница ошибки».

Ошибки загрузки JS-чанков

Ошибки загрузки чанков возможны из-за сети или нового деплоя (старые хэшированные URL чанков перестают работать). Nuxt по умолчанию обрабатывает их жёсткой перезагрузкой при неудачной загрузке чанка при навигации.

Поведение меняется опцией experimental.emitRouteChunkError: false — не перехватывать такие ошибки, manual — обрабатывать самостоятельно. Пример реализации: chunk-reload.client.ts.

Страница ошибки

При фатальной ошибке (любая необработанная на сервере или созданная с fatal: true на клиенте) Nuxt отдаёт JSON (если запрос с заголовком Accept: application/json) или показывает полноэкранную страницу ошибки.

Ошибка на сервере может возникнуть при:

  • выполнении плагинов Nuxt
  • рендеринге Vue-приложения в HTML
  • выбросе ошибки в серверном API-маршруте

На клиенте — при:

  • выполнении плагинов Nuxt
  • перед монтированием (хук app:beforeMount)
  • монтировании, если ошибка не перехвачена onErrorCaptured или vue:error
  • инициализации и монтировании приложения в браузере (хук app:mounted).
Все хуки жизненного цикла Nuxt.

Страницу ошибки по умолчанию можно заменить, добавив ~/error.vue в исходную директорию приложения (рядом с app.vue).

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

const props = defineProps({
  error: Object as () => NuxtError,
})

const handleError = () => clearError({ redirect: '/' })
</script>

<template>
  <div>
    <h2>{{ error?.status }}</h2>
    <button @click="handleError">
      Clear errors
    </button>
  </div>
</template>
Подробнее о error.vue и его использовании.

Для кастомной обработки ошибок рекомендуется композабл onErrorCaptured в setup страницы/компонента или хук vue:error в плагине Nuxt.

plugins/error-handler.ts
export default defineNuxtPlugin((nuxtApp) => {
  nuxtApp.hook('vue:error', (err) => {
    //
  })
})

Чтобы убрать страницу ошибки, вызовите clearError с опциональным путём редиректа (например, на «безопасную» страницу).

Перед использованием всего, что зависит от плагинов Nuxt ($route, useRouter и т.д.), проверяйте контекст: если ошибку выбросил плагин, он не будет выполнен заново до вызова clearError.
Отображение страницы ошибки — отдельная загрузка страницы, поэтому зарегистрированный middleware выполнится снова. В middleware можно использовать useError, чтобы проверить, обрабатывается ли ошибка.
В Node 16 установка cookie при рендере страницы ошибки может перезаписать ранее установленные. Рекомендуется более новая версия Node (Node 16 вышла из поддержки в сентябре 2023).

Утилиты для ошибок

useError

TS Signature
function useError (): Ref<Error | { url, status, statusText, message, description, data }>

Возвращает текущую обрабатываемую глобальную ошибку Nuxt.

Подробнее о композабле useError.

createError

TS Signature
function createError (err: string | { cause, data, message, name, stack, status, statusText, fatal }): Error

Создаёт объект ошибки с дополнительными метаданными. Можно передать строку (будет в message) или объект со свойствами. Используется во Vue и на сервере и предназначен для выброса.

При выбросе ошибки, созданной через createError:

  • на сервере отобразится полноэкранная страница ошибки, которую можно сбросить через clearError;
  • на клиенте будет выброшена нефатальная ошибка для обработки. Чтобы показать полноэкранную страницу, передайте fatal: true.
pages/movies/[slug].vue
<script setup lang="ts">
const route = useRoute()
const { data } = await useFetch(`/api/movies/${route.params.slug}`)

if (!data.value) {
  throw createError({
    status: 404,
    statusText: 'Page Not Found',
  })
}
</script>
statusText — короткий HTTP-статус (например "Not Found"), только табуляция, пробелы и видимый ASCII ([\t\u0020-\u007E]). Подробные или многострочные описания задавайте в свойстве message.
Подробнее об утилите createError.

showError

TS Signature
function showError (err: string | Error | { status, statusText }): Error

Вызов в любой момент на клиенте или (на сервере) в middleware, плагинах или в setup() показывает полноэкранную страницу ошибки. Сброс — через clearError.

Рекомендуется вместо этого использовать throw createError().

Подробнее об утилите showError.

clearError

TS Signature
function clearError (options?: { redirect?: string }): Promise<void>

Сбрасывает текущую обрабатываемую ошибку Nuxt. Опционально принимает путь для редиректа.

Подробнее об утилите clearError.

Ошибки внутри компонента

Компонент <NuxtErrorBoundary> обрабатывает ошибки на клиенте внутри приложения, не заменяя весь сайт страницей ошибки.

Он перехватывает ошибки в своём слоте по умолчанию. На клиенте ошибка не всплывает на верхний уровень, вместо неё рендерится слот #error.

Слот #error получает проп error. (Если установить error = null, будет повторный рендер слота по умолчанию; убедитесь, что ошибка полностью устранена, иначе слот ошибки отобразится снова.)

При переходе на другой маршрут ошибка сбрасывается автоматически.
app/pages/index.vue
<template>
  <!-- какой-то контент -->
  <NuxtErrorBoundary @error="someErrorLogger">
    <template #error="{ error, clearError }">
      Локальный вывод ошибки: {{ error }}
      <button @click="clearError">
        Сбросить ошибку
      </button>
    </template>
  </NuxtErrorBoundary>
</template>
Прочитайте и отредактируйте живой пример в Docs > 4 X > Examples > Advanced > Error Handling.