---
title: "错误处理"
description: "了解如何在 Nuxt 中捕获和处理错误。"
canonical_url: "https://nuxt.zhcndoc.com/docs/4.x/getting-started/error-handling"
---
# 错误处理

> 了解如何在 Nuxt 中捕获和处理错误。

Nuxt 是一个全栈框架，这意味着在不同的上下文中可能会发生一些无法预防的运行时用户错误，来源包括：

- Vue 渲染生命周期中的错误（SSR 和 CSR）
- 服务器和客户端启动错误（SSR + CSR）
- Nitro 服务器生命周期中的错误（[`server/`](https://nuxt.zhcndoc.com/docs/4.x/directory-structure/server) 目录）
- 下载 JS 分块时发生的错误

::tip
**SSR** 表示 **服务器端渲染（Server-Side Rendering）**，**CSR** 表示 **客户端渲染（Client-Side Rendering）**。
::

## Vue 错误

你可以使用 [`onErrorCaptured`](https://vue.zhcndoc.com/api/composition-api-lifecycle.html#onerrorcaptured) 钩子来捕获 Vue 错误。

此外，Nuxt 提供了一个 [`vue:error`](https://nuxt.zhcndoc.com/docs/4.x/api/advanced/hooks#app-hooks-runtime) 钩子，当任何错误向上传播至顶层时会被调用。

如果你在使用错误上报框架，可以通过 [`vueApp.config.errorHandler`](https://vue.zhcndoc.com/api/application.html#app-config-errorhandler) 提供一个全局处理器。它会接收所有 Vue 错误，即使这些错误已被处理。

```ts twoslash [plugins/error-handler.ts]
export default defineNuxtPlugin((nuxtApp) => {
  nuxtApp.vueApp.config.errorHandler = (error, instance, info) => {
    // 处理错误，例如上报到服务
  }

  // 也可以这样使用
  nuxtApp.hook('vue:error', (error, instance, info) => {
    // 处理错误，例如上报到服务
  })
})
```

::note
请注意，`vue:error` 钩子是基于 [`onErrorCaptured`](https://vue.zhcndoc.com/api/composition-api-lifecycle.html#onerrorcaptured) 生命周期钩子。
::

## 启动错误

如果在启动 Nuxt 应用时发生任何错误，Nuxt 会调用 `app:error` 钩子。

包括：

- 运行 [Nuxt 插件](https://nuxt.zhcndoc.com/docs/4.x/directory-structure/app/plugins)
- 处理 `app:created` 和 `app:beforeMount` 钩子
- 将 Vue 应用渲染为 HTML（SSR 期间）
- 挂载应用（在客户端），不过此情况应使用 `onErrorCaptured` 或 `vue:error` 处理
- 处理 `app:mounted` 钩子

## Nitro 服务器错误

目前无法为这些错误定义服务器端处理器，但可以渲染错误页面，参见[渲染错误页面](https://nuxt.zhcndoc.com/docs/4.x/getting-started/error-handling#error-page)部分。

## JS 分块错误

你可能会遇到分块加载错误，原因是网络连接失败或新的部署（使旧的带哈希的 JS 分块 URL 失效）。Nuxt 内置了处理分块加载错误的支持：在路由导航期间如果某个分块加载失败，会执行硬刷新。

你可以通过将 `experimental.emitRouteChunkError` 设置为 `false`（完全禁用对这些错误的钩子处理）或设置为 `manual`（如果你希望自行处理）来更改此行为。如果你想手动处理分块加载错误，可以参考[自动实现](https://github.com/nuxt/nuxt/blob/main/packages/nuxt/src/app/plugins/chunk-reload.client.ts)来获取思路。

## 错误页面

::note
当 Nuxt 遇到严重错误（服务器上任何未处理的错误，或客户端使用 `fatal: true` 创建的错误）时，它将根据请求头决定要么渲染 JSON 响应（如果请求带有 `Accept: application/json`），要么触发一个全屏错误页面。设置 `future.compatibilityVersion: 5` 后，页面错误始终触发错误页面，而服务器路由或服务器中间件中抛出的错误会返回 JSON 响应。
::

在服务器生命周期中可能发生错误的情况包括：

- 处理你的 Nuxt 插件
- 将你的 Vue 应用渲染为 HTML
- 服务器 API 路由抛出错误

在客户端也可能发生错误的情况包括：

- 处理你的 Nuxt 插件
- 在挂载应用之前（`app:beforeMount` 钩子）
- 如果未使用 `onErrorCaptured` 或 `vue:error` 钩子处理，在挂载应用时发生错误
- Vue 应用在浏览器中初始化并挂载（`app:mounted`）

::read-more{to="https://nuxt.zhcndoc.com/docs/4.x/api/advanced/hooks"}
了解所有 Nuxt 生命周期钩子。
::

通过在应用源目录中（与 `app.vue` 并列）添加 `~/error.vue` 来自定义默认错误页面。

<!-- TODO：Twoslash 尚不支持 tsconfig 路径 -->

```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">
      清除错误
    </button>
  </div>
</template>
```

::read-more{to="https://nuxt.zhcndoc.com/docs/4.x/directory-structure/app/error"}
了解有关 `error.vue` 及其用途的更多信息。
::

对于自定义错误，我们强烈建议使用 `onErrorCaptured` 可组合函数（可在页面/组件的 setup 函数中调用）或在 Nuxt 插件中配置的运行时 `vue:error` 钩子。

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

当你准备好移除错误页面时，可以调用 [`clearError`](https://nuxt.zhcndoc.com/docs/4.x/api/utils/clear-error) 辅助函数，它接受一个可选的重定向路径（例如，如果你想导航到一个“安全”页面）。

::important
在使用依赖于 Nuxt 插件的任何内容（例如 `$route` 或 `useRouter`）之前，请务必先检查，因为如果某个插件抛出了错误，该插件在清除错误之前不会重新运行。
::

::note
渲染错误页面是一次完全独立的页面加载，这意味着任何已注册的中间件都会再次运行。你可以在中间件中使用 [`useError`](https://nuxt.zhcndoc.com/docs/4.x/getting-started/error-handling#useerror) 来检查是否正在处理错误。
::

::note
如果你在 Node 16 上运行，并且在渲染错误页面时设置了任何 cookie，它们将会[覆盖先前设置的 cookie](https://github.com/nuxt/nuxt/pull/20585)。我们建议使用更新版本的 Node，因为 Node 16 已于 2023 年 9 月到达生命周期结束。
::

## 错误工具

### `useError`

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

此函数将返回当前正在处理的全局 Nuxt 错误。

::read-more{to="https://nuxt.zhcndoc.com/docs/4.x/api/composables/use-error"}
了解有关 `useError` 可组合函数的更多信息。
::

### `createError`

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

创建一个带有附加元数据的错误对象。你可以传入字符串作为错误的 `message`，也可以传入包含错误属性的对象。该函数可在应用的 Vue 和服务器部分使用，并且用于抛出错误。

如果你抛出使用 `createError` 创建的错误：

- 在服务器端，它会触发一个全屏错误页面，你可以使用 [`clearError`](https://nuxt.zhcndoc.com/docs/4.x/getting-started/error-handling#clearerror) 清除该页面。
- 在客户端，它会抛出一个非致命错误供你处理。如果你需要触发全屏错误页面，可以将 `fatal: true` 设置为 `true`。

在开发环境中，错误的 `cause` 会被保留并暴露给你的错误页面，以便你追踪原始错误；在生产环境中，错误响应或错误页面负载中永远不会包含 `cause`。

```vue twoslash [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: '未找到页面',
  })
}
</script>
```

::tip
`statusText` 属性适用于简短的、符合 HTTP 标准的状态文本（例如，“未找到”）。它应仅包含水平制表符、空格和可见的 ASCII 字符（`[\t\u0020-\u007E]`）。

对于任何详细描述、多行消息或包含非 ASCII 字符的内容，应始终使用 `message` 属性。
::

::read-more{to="https://nuxt.zhcndoc.com/docs/4.x/api/utils/create-error"}
了解有关 `createError` 工具的更多信息。
::

### `showError`

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

你可以随时在客户端调用此函数，或者（在服务器端）直接在中间件、插件或 `setup()` 函数中调用。它会触发一个全屏错误页面，你可以使用 [`clearError`](https://nuxt.zhcndoc.com/docs/4.x/getting-started/error-handling#clearerror) 清除该页面。

建议改为使用 `throw createError()`。

::read-more{to="https://nuxt.zhcndoc.com/docs/4.x/api/utils/show-error"}
了解有关 `showError` 工具的更多信息。
::

### `clearError`

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

此函数将清除当前正在处理的 Nuxt 错误。它还接受一个可选的重定向路径（例如，如果你想导航到一个“安全”页面）。

::read-more{to="https://nuxt.zhcndoc.com/docs/4.x/api/utils/clear-error"}
了解有关 `clearError` 工具的更多信息。
::

## 在组件中渲染错误

Nuxt 还提供了 [`<NuxtErrorBoundary>`](https://nuxt.zhcndoc.com/docs/4.x/api/components/nuxt-error-boundary) 组件，让你能够在应用中处理客户端错误，而不必用错误页面替换整个网站。

该组件负责处理发生在其默认插槽中的错误。在客户端，它会阻止错误向顶层冒泡，并渲染 `#error` 插槽作为替代。

`#error` 插槽将接收 `error` 作为 prop。（如果你将 `error = null`，它会触发默认插槽的重新渲染；你需要确保错误已被完全解决，否则错误插槽将再次被渲染。）

::tip
如果你导航到其它路由，错误将会自动清除。
::

```vue [app/pages/index.vue]
<template>
  <!-- 一些内容 -->
  <NuxtErrorBoundary @error="someErrorLogger">
    <!-- 使用默认插槽渲染内容 -->
    <template #error="{ error, clearError }">
      你可以在这里本地显示错误：{{ error }}
      <button @click="clearError">
        清除错误
      </button>
    </template>
  </NuxtErrorBoundary>
</template>
```

::link-example{to="https://nuxt.zhcndoc.com/docs/examples/advanced/error-handling"}
::


## Sitemap

See the full [sitemap](https://nuxt.zhcndoc.com/sitemap.md) for all pages.
