mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-26 23:52:06 +00:00
f26a801775
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Daniel Roe <daniel@roe.dev>
252 lines
9.2 KiB
Markdown
252 lines
9.2 KiB
Markdown
---
|
|
title: 'Error Handling'
|
|
description: 'Learn how to catch and handle errors in Nuxt.'
|
|
navigation.icon: i-ph-bug-beetle-duotone
|
|
---
|
|
|
|
Nuxt 3 is a full-stack framework, which means there are several sources of unpreventable user runtime errors that can happen in different contexts:
|
|
|
|
- Errors during the Vue rendering lifecycle (SSR & CSR)
|
|
- Errors during Nitro server lifecycle ([`server/`](/docs/guide/directory-structure/server) directory)
|
|
- Server and client startup errors (SSR + CSR)
|
|
- Errors downloading JS chunks
|
|
|
|
::callout
|
|
**SSR** stands for **Server-Side Rendering** and **CSR** for **Client-Side Rendering**.
|
|
::
|
|
|
|
## Vue Rendering Lifecycle
|
|
|
|
You can hook into Vue errors using [`onErrorCaptured`](https://vuejs.org/api/composition-api-lifecycle.html#onerrorcaptured).
|
|
|
|
In addition, Nuxt provides a [`vue:error`](/docs/api/advanced/hooks#app-hooks-runtime) hook that will be called if any errors propagate up to the top level.
|
|
|
|
If you are using an error reporting framework, you can provide a global handler through [`vueApp.config.errorHandler`](https://vuejs.org/api/application.html#app-config-errorhandler). It will receive all Vue errors, even if they are handled.
|
|
|
|
```ts [plugins/error-handler.ts]
|
|
export default defineNuxtPlugin((nuxtApp) => {
|
|
nuxtApp.vueApp.config.errorHandler = (error, instance, info) => {
|
|
// handle error, e.g. report to a service
|
|
}
|
|
|
|
// Also possible
|
|
nuxtApp.hook('vue:error', (error, instance, info) => {
|
|
// handle error, e.g. report to a service
|
|
})
|
|
})
|
|
```
|
|
|
|
::callout
|
|
Note that the `vue:error` hook is based on [`onErrorCaptured`](https://vuejs.org/api/composition-api-lifecycle.html#onerrorcaptured) lifecycle hook.
|
|
::
|
|
|
|
## Startup Errors
|
|
|
|
Nuxt will call the `app:error` hook if there are any errors in starting your Nuxt application.
|
|
|
|
This includes:
|
|
- running [Nuxt plugins](/docs/guide/directory-structure/plugins)
|
|
- processing `app:created` and `app:beforeMount` hooks
|
|
- rendering your Vue app to HTML (during SSR)
|
|
- mounting the app (on client-side), though you should handle this case with `onErrorCaptured` or with `vue:error`
|
|
- processing the `app:mounted` hook
|
|
|
|
## Nitro Server Lifecycle
|
|
|
|
You cannot currently define a server-side handler for these errors, but can render an error page, see the [Render an Error Page](#error-page) section.
|
|
|
|
## Errors with JS chunks
|
|
|
|
You might encounter chunk loading errors due to a network connectivity failure or a new deployment (which invalidates your old, hashed JS chunk URLs). Nuxt provides built-in support for handling chunk loading errors by performing a hard reload when a chunk fails to load during route navigation.
|
|
|
|
You can change this behavior by setting `experimental.emitRouteChunkError` to `false` (to disable hooking into these errors at all) or to `manual` if you want to handle them yourself. If you want to handle chunk loading errors manually, you can check out the [the automatic implementation](https://github.com/nuxt/nuxt/blob/main/packages/nuxt/src/app/plugins/chunk-reload.client.ts) for ideas.
|
|
|
|
## Error Page
|
|
|
|
::callout
|
|
When Nuxt encounters a fatal error (any unhandled error on the server, or an error created with `fatal: true` on the client) it will either render a JSON response (if requested with `Accept: application/json` header) or trigger a full-screen error page.
|
|
::
|
|
|
|
An error may occur during the server lifecycle when:
|
|
- processing your Nuxt plugins
|
|
- rendering your Vue app into HTML
|
|
- a server API route throws an error
|
|
|
|
It can also occur on the client side when:
|
|
- processing your Nuxt plugins
|
|
- before mounting the application (`app:beforeMount` hook)
|
|
- mounting your app if the error was not handled with `onErrorCaptured` or `vue:error` hook
|
|
- the Vue app is initialized and mounted in browser (`app:mounted`).
|
|
|
|
::read-more{to="/docs/api/advanced/hooks"}
|
|
Discover all the Nuxt lifecycle hooks.
|
|
::
|
|
|
|
Customize the default error page by adding `~/error.vue` in the source directory of your application, alongside `app.vue`.
|
|
|
|
```vue [error.vue]
|
|
<script setup lang="ts">
|
|
const props = defineProps({
|
|
error: Object
|
|
})
|
|
|
|
const handleError = () => clearError({ redirect: '/' })
|
|
</script>
|
|
|
|
<template>
|
|
<div>
|
|
<h2>{{ error.statusCode }}</h2>
|
|
<button @click="handleError">Clear errors</button>
|
|
</div>
|
|
</template>
|
|
```
|
|
|
|
::callout
|
|
Although it is called an 'error page' it's not a route and shouldn't be placed in your `~/pages` directory. For the same reason, you shouldn't use `definePageMeta` within this page.
|
|
::
|
|
|
|
The error page has a single prop - `error` which contains an error for you to handle.
|
|
|
|
The `error` object provides the fields:
|
|
```ts
|
|
{
|
|
url: string
|
|
statusCode: number
|
|
statusMessage: string
|
|
message: string
|
|
description: string
|
|
data: any
|
|
}
|
|
```
|
|
|
|
If you have an error with custom fields they will be lost; you should assign them to `data` instead:
|
|
|
|
```ts
|
|
throw createError({
|
|
statusCode: 404,
|
|
statusMessage: 'Page Not Found',
|
|
data: {
|
|
myCustomField: true
|
|
}
|
|
})
|
|
```
|
|
|
|
For custom errors we highly recommend to use `onErrorCaptured` composable that can be called in a page/component setup function or `vue:error` runtime nuxt hook that can be configured in a nuxt plugin.
|
|
|
|
```ts [plugins/error-handler.ts]
|
|
export default defineNuxtPlugin(nuxtApp => {
|
|
nuxtApp.hook('vue:error', (err) => {
|
|
//
|
|
})
|
|
})
|
|
```
|
|
|
|
When you are ready to remove the error page, you can call the [`clearError`](/docs/api/utils/clear-error) helper function, which takes an optional path to redirect to (for example, if you want to navigate to a 'safe' page).
|
|
|
|
::callout
|
|
Make sure to check before using anything dependent on Nuxt plugins, such as `$route` or `useRouter`, as if a plugin threw an error, then it won't be re-run until you clear the error.
|
|
::
|
|
|
|
::callout
|
|
If you are running on Node 16 and you set any cookies when rendering your error page, they will [overwrite cookies previously set](https://github.com/nuxt/nuxt/pull/20585). We recommend using a newer version of Node as Node 16 reached end-of-life in September 2023.
|
|
::
|
|
|
|
## Error Utils
|
|
|
|
### `useError`
|
|
|
|
```ts [TS Signature]
|
|
function useError (): Ref<Error | { url, statusCode, statusMessage, message, description, data }>
|
|
```
|
|
|
|
This function will return the global Nuxt error that is being handled.
|
|
|
|
::read-more{to="/docs/api/composables/use-error"}
|
|
Read more about `useError` composable.
|
|
::
|
|
|
|
### `createError`
|
|
|
|
```ts [TS Signature]
|
|
function createError (err: { cause, data, message, name, stack, statusCode, statusMessage, fatal }): Error
|
|
```
|
|
|
|
Create an error object with additional metadata. It is usable in both the Vue and Server portions of your app, and is meant to be thrown.
|
|
|
|
If you throw an error created with `createError`:
|
|
- on server-side, it will trigger a full-screen error page which you can clear with [`clearError`](#clearerror).
|
|
- on client-side, it will throw a non-fatal error for you to handle. If you need to trigger a full-screen error page, then you can do this by setting `fatal: true`.
|
|
|
|
```vue [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({
|
|
statusCode: 404,
|
|
statusMessage: 'Page Not Found'
|
|
})
|
|
}
|
|
</script>
|
|
```
|
|
|
|
::read-more{to="/docs/api/utils/create-error"}
|
|
Read more about `createError` util.
|
|
::
|
|
|
|
### `showError`
|
|
|
|
```ts [TS Signature]
|
|
function showError (err: string | Error | { statusCode, statusMessage }): Error
|
|
```
|
|
|
|
You can call this function at any point on client-side, or (on server side) directly within middleware, plugins or `setup()` functions. It will trigger a full-screen error page which you can clear with [`clearError`](#clearerror).
|
|
|
|
It is recommended instead to use `throw createError()`.
|
|
|
|
::read-more{to="/docs/api/utils/show-error"}
|
|
Read more about `showError` util.
|
|
::
|
|
|
|
### `clearError`
|
|
|
|
```ts [TS Signature]
|
|
function clearError (options?: { redirect?: string }): Promise<void>
|
|
```
|
|
|
|
This function will clear the currently handled Nuxt error. It also takes an optional path to redirect to (for example, if you want to navigate to a 'safe' page).
|
|
|
|
::read-more{to="/docs/api/utils/clear-error"}
|
|
Read more about `clearError` util.
|
|
::
|
|
|
|
## Render Error in Component
|
|
|
|
Nuxt also provides a [`<NuxtErrorBoundary>`](/docs/api/components/nuxt-error-boundary) component that allows you to handle client-side errors within your app, without replacing your entire site with an error page.
|
|
|
|
This component is responsible for handling errors that occur within its default slot. On client-side, it will prevent the error from bubbling up to the top level, and will render the `#error` slot instead.
|
|
|
|
The `#error` slot will receive `error` as a prop. (If you set `error = null` it will trigger re-rendering the default slot; you'll need to ensure that the error is fully resolved first or the error slot will just be rendered a second time.)
|
|
|
|
::callout
|
|
If you navigate to another route, the error will be cleared automatically.
|
|
::
|
|
|
|
```vue [pages/index.vue]
|
|
<template>
|
|
<!-- some content -->
|
|
<NuxtErrorBoundary @error="someErrorLogger">
|
|
<!-- You use the default slot to render your content -->
|
|
<template #error="{ error, clearError }">
|
|
You can display the error locally here: {{ error }}
|
|
<button @click="clearError">
|
|
This will clear the error.
|
|
</button>
|
|
</template>
|
|
</NuxtErrorBoundary>
|
|
</template>
|
|
```
|
|
|
|
:link-example{to="/docs/examples/advanced/error-handling"}
|