nuxt: Bug: Handling errors with the NuxtErrorBoundary component

The NuxtErrorBoundary component does not seem to work as expected:

The #error slot will receive error as a prop. (If you set error = null it will trigger re-rendering the default slot;

Example:

// app.vue
<template>
  <NuxtErrorBoundary>
    <NuxtPage/>
    <template #error="{ error }">
      <p>An error occurred: {{ error }}</p>
      <button @click="() => clearError({ redirect: '/' })">
        This will clear the error.
      </button>
    </template>
  </NuxtErrorBoundary>
</template>

Problem 1:

The error is NOT cleared at all when the button is clicked. The error message still can be seen on the screen.

Problem 2:

The Home page is NOT rendered at all when the route is redirected to / successfully. It is still rendering the error component and message.

Any ideas?

About this issue

  • Original URL
  • State: open
  • Created 2 years ago
  • Reactions: 16
  • Comments: 20 (4 by maintainers)

Most upvoted comments

FWIW, I’m using a home-grown components/ErrorBoundary.vue:

<script setup lang="ts">
const error = ref<Error>()

function clearError() {
  error.value = undefined
}

onErrorCaptured(err => {
  error.value = err
  return false
})

const route = useRoute()
watch(
  () => route.fullPath,
  () => {
    error.value = undefined
  },
)
</script>

<template>
  <slot v-if="!error" />
  <slot v-else name="error" :error="error" :clear-error="clearError" />
</template>

Features:

  • does what NuxtErrorBoundary advertises
  • works with async components
  • resets automatically on route change
  • can be used on parent.vue alongside parent/child1.vue and parent/child2.vue (handles crash in child1 and allows to switch to child2)

This is how one can use it with nuxt-page:

<error-boundary>
  <nuxt-page v-bind="$attrs" />
  <template #error="{ error, clearError }">
    <p>{{ error }}</p>
    <button @click="clearError">Try again</button>
  </template>
</error-boundary>

Any update about this issue ? When NuxtErrorBoundary is used the full error page shows up.

With NuxtErrorBoundary in app.vue, ssr: false, and an error thrown from a page component, nothing appears at all, just an error in the console. The error will show properly on page navigation, but not on initial page load.

[Vue warn]
[Vue warn]: Unhandled error during execution of setup function 
  at <Index onVnodeUnmounted=fn<onVnodeUnmounted> ref=Ref< undefined > > 
  at <RouteProvider key="/projects/817c4d302bdaae79da0a6778" routeProps= 
Object { Component: {…}, route: {…} }
 pageKey="/projects/817c4d302bdaae79da0a6778"  ... > 
  at <BaseTransition onAfterLeave= 
Array [ onAfterLeave() ]
 mode="out-in" appear=false  ... > 
  at <Transition onAfterLeave= 
Array [ onAfterLeave() ]
 name="page" mode="out-in" > 
  at <RouterView name=undefined route=undefined > 
  at <NuxtPage> 
  at <[projectId] onVnodeUnmounted=fn<onVnodeUnmounted> ref=Ref< 
Proxy { <target>: Proxy, <handler>: {…} }
 > > 
  at <RouteProvider key="/projects/817c4d302bdaae79da0a6778" routeProps= 
Object { Component: {…}, route: {…} }
 pageKey="/projects/817c4d302bdaae79da0a6778"  ... > 
  at <BaseTransition onAfterLeave= 
Array [ onAfterLeave() ]
 mode="out-in" appear=false  ... > 
  at <Transition onAfterLeave= 
Array [ onAfterLeave() ]
 name="page" mode="out-in" > 
  at <RouterView name=undefined route=undefined > 
  at <NuxtPage> 
  at <Anonymous onError=fn<logError> > 
  at <App key=2 > 
  at <NuxtRoot> chunk-3NMN3MUW.js:1381

Error
Uncaught (in promise) Error: Project not found
    NuxtJS 3
    setup index.vue:20
    callWithErrorHandling chunk-3NMN3MUW.js:1580
    setupStatefulComponent chunk-3NMN3MUW.js:7383
    setupComponent chunk-3NMN3MUW.js:7346
    mountComponent chunk-3NMN3MUW.js:6033
    processComponent chunk-3NMN3MUW.js:6011
    patch chunk-3NMN3MUW.js:5700
    componentUpdateFn chunk-3NMN3MUW.js:6128
    run chunk-3NMN3MUW.js:405
    update chunk-3NMN3MUW.js:6220
    setupRenderEffect chunk-3NMN3MUW.js:6228
    mountComponent chunk-3NMN3MUW.js:6046
    processComponent chunk-3NMN3MUW.js:6011
    patch chunk-3NMN3MUW.js:5700
    mountSuspense chunk-3NMN3MUW.js:2417
    process chunk-3NMN3MUW.js:2397
    patch chunk-3NMN3MUW.js:5704
    componentUpdateFn chunk-3NMN3MUW.js:6128
    run chunk-3NMN3MUW.js:405
    update chunk-3NMN3MUW.js:6220
    setupRenderEffect chunk-3NMN3MUW.js:6228
    mountComponent chunk-3NMN3MUW.js:6046
    processComponent chunk-3NMN3MUW.js:6011
    patch chunk-3NMN3MUW.js:5700
    componentUpdateFn chunk-3NMN3MUW.js:6128
    run chunk-3NMN3MUW.js:405
    update chunk-3NMN3MUW.js:6220
    setupRenderEffect chunk-3NMN3MUW.js:6228
    mountComponent chunk-3NMN3MUW.js:6046
    processComponent chunk-3NMN3MUW.js:6011
    patch chunk-3NMN3MUW.js:5700
    componentUpdateFn chunk-3NMN3MUW.js:6128
    run chunk-3NMN3MUW.js:405
    update chunk-3NMN3MUW.js:6220
    setupRenderEffect chunk-3NMN3MUW.js:6228
    mountComponent chunk-3NMN3MUW.js:6046
    processComponent chunk-3NMN3MUW.js:6011
    patch chunk-3NMN3MUW.js:5700
    componentUpdateFn chunk-3NMN3MUW.js:6128
    run chunk-3NMN3MUW.js:405
    update chunk-3NMN3MUW.js:6220
    setupRenderEffect chunk-3NMN3MUW.js:6228
    mountComponent chunk-3NMN3MUW.js:6046
    processComponent chunk-3NMN3MUW.js:6011
    patch chunk-3NMN3MUW.js:5700
    mountChildren chunk-3NMN3MUW.js:5845
    mountElement chunk-3NMN3MUW.js:5777
    processElement chunk-3NMN3MUW.js:5764
    patch chunk-3NMN3MUW.js:5698
    componentUpdateFn chunk-3NMN3MUW.js:6128
    run chunk-3NMN3MUW.js:405
    update chunk-3NMN3MUW.js:6220
    setupRenderEffect chunk-3NMN3MUW.js:6228
    registerDep chunk-3NMN3MUW.js:2696
    promise callback*registerDep chunk-3NMN3MUW.js:2682
    mountComponent chunk-3NMN3MUW.js:6039
    processComponent chunk-3NMN3MUW.js:6011
    patch chunk-3NMN3MUW.js:5700
    componentUpdateFn chunk-3NMN3MUW.js:6128
    run chunk-3NMN3MUW.js:405
    update chunk-3NMN3MUW.js:6220
    setupRenderEffect chunk-3NMN3MUW.js:6228
    mountComponent chunk-3NMN3MUW.js:6046
    processComponent chunk-3NMN3MUW.js:6011
    patch chunk-3NMN3MUW.js:5700
    mountSuspense chunk-3NMN3MUW.js:2417
    process chunk-3NMN3MUW.js:2397
    patch chunk-3NMN3MUW.js:5704
    componentUpdateFn chunk-3NMN3MUW.js:6128
    run chunk-3NMN3MUW.js:405
    update chunk-3NMN3MUW.js:6220
    setupRenderEffect chunk-3NMN3MUW.js:6228
    mountComponent chunk-3NMN3MUW.js:6046
    processComponent chunk-3NMN3MUW.js:6011
    patch chunk-3NMN3MUW.js:5700
    componentUpdateFn chunk-3NMN3MUW.js:6128
    run chunk-3NMN3MUW.js:405
    update chunk-3NMN3MUW.js:6220
    setupRenderEffect chunk-3NMN3MUW.js:6228
    mountComponent chunk-3NMN3MUW.js:6046
    processComponent chunk-3NMN3MUW.js:6011
    patch chunk-3NMN3MUW.js:5700
    componentUpdateFn chunk-3NMN3MUW.js:6128
    run chunk-3NMN3MUW.js:405
index.mjs:100:5

Hey, work for me in app.vue image

Trying to use NuxtErrorBoundary on a component/page level, and I dont think its preventing global error page from rendering. I’m throwing createError from API and trying to gracefully show it while not rendering the global error page. Hopefully this ifxes soon… I’m about to pull all my hair out.

Here is my own take on an ErrorBoundary component:

<script lang="ts">
let handlerSetup = false
const handlers: Array<() => void> = []
</script>

<script lang="ts" setup>
const error = shallowRef<any>(null)

onErrorCaptured((err) => {
  // eslint-disable-next-line no-console
  console.log('error', err)
  error.value = err
  return false
})

const router = useRouter()

async function clearError(options: { redirect?: any } = {}) {
  if (options.redirect) {
    await router.push(options.redirect)
  }
  error.value = null
}

if (!handlerSetup) {
  router.beforeEach(() => {
    handlers.forEach(handler => handler())
  })
  handlerSetup = true
}

handlers.push(clearError)

onBeforeUnmount(() => {
  const index = handlers.indexOf(clearError)
  if (index !== -1) {
    handlers.splice(index, 1)
  }
})
</script>

<template>
  <slot
    v-if="!error"
  />

  <slot
    v-else
    name="error"
    :error="error"
    :clear-error="clearError"
  />
</template>

Hi I have the same issue using NuxtErrorBoundary around NuxtPage 👍

    <NuxtErrorBoundary>
        <NuxtPage />
    </NuxtErrorBoundary>

Any idea or workaround ?

Hey! Could you kindly provide a reproduction via StackBlitz or CodeSandbox? 🙏