Vue cookbook · Intermediate
Catch component errors with an error boundary
One failing widget crashes the whole page with a blank screen.
Approach
Build an ErrorBoundary component with onErrorCaptured that shows a fallback for its subtree and stops the
error from propagating, and report all errors centrally with app.config.errorHandler.
Solution
<!-- ErrorBoundary.vue -->
<script setup lang="ts">
import { onErrorCaptured, ref } from "vue";
defineProps<{ fallback?: string }>();
const error = ref<Error | null>(null);
onErrorCaptured((err) => {
error.value = err instanceof Error ? err : new Error(String(err));
return false; // stop propagation: the rest of the page keeps working
});
</script>
<template>
<div v-if="error" role="alert">
<p>{{ fallback ?? "This section couldn't be loaded." }}</p>
<button @click="error = null">Try again</button>
</div>
<slot v-else />
</template>
// main.ts
import { createApp } from "vue";
import App from "./App.vue";
const app = createApp(App);
app.config.errorHandler = (err, instance, info) => {
// send to Sentry or your error tracker
console.error("Vue error", info, err);
};
app.mount("#app");
Pitfalls
- Swallowing errors in boundaries without reporting them.
- Expecting
onErrorCapturedto catch errors in event handlers' async code that isn't awaited by Vue; handle those in the handler or withwindow.onunhandledrejection. - One boundary around the whole app, which still blanks everything.
Variations
- In Nuxt,
<NuxtErrorBoundary>provides the same behaviour with an#errorslot. - Combine with
Suspenseto show loading and error states for async setup.
Further reading: onErrorCaptured
Reference: https://vuejs.org/api/composition-api-lifecycle.html#onerrorcaptured
More Vue recipes
- Access child component methods with template refs and defineExpose
- Add SEO metadata and structured data in Nuxt
- Build an accessible modal with Teleport
- Build custom inputs with defineModel and modifiers
- Debounce user input with a custom ref
- Fetch data in a composable and cancel stale requests
- Fetch, refresh and share data with Nuxt useFetch
- Implement a dark mode toggle that respects system settings