JAVASCRIPT

Global Error Handling and Component Error Boundaries in Vue 3

Implement robust error handling in Vue 3 applications using `app.config.errorHandler` for global catches and `errorCaptured` lifecycle hook for component-specific error boundaries.

// main.js
import { createApp } from 'vue';
import App from './App.vue';

const app = createApp(App);

// 1. Global Error Handler
app.config.errorHandler = (err, vm, info) => {
  console.error('Global Error Handler Caught:', err, vm, info);
  // Report to an error tracking service (e.g., Sentry, Bugsnag)
};

// Global warning handler (optional, for non-critical issues)
app.config.warnHandler = (msg, vm, trace) => {
  // console.warn('Global Warning Handler Caught:', msg, vm, trace);
};

app.mount('#app');


// components/ErrorBoundary.vue (Example of a component error boundary)
<template>
  <div v-if="hasError" class="error-boundary">
    <h2>Something went wrong in this component!</h2>
    <p>We're sorry for the inconvenience. Please try refreshing the page or contact support.</p>
    <details v-if="error">
      <summary>Error Details</summary>
      <pre>{{ error }}</pre>
      <pre>{{ errorInfo }}</pre>
    </details>
  </div>
  <slot v-else></slot>
</template>

<script setup>
import { ref, onErrorCaptured } from 'vue';

const hasError = ref(false);
const error = ref(null);
const errorInfo = ref(null);

onErrorCaptured((err, vm, info) => {
  hasError.value = true;
  error.value = err;
  errorInfo.value = info;

  console.error('Component Error Boundary Caught:', err, vm, info);

  // Return `false` to stop the error from propagating further up the component tree.
  // If you return `true` or nothing, it continues to the global handler.
  return false;
});
</script>

<style scoped>
.error-boundary {
  border: 2px solid red;
  padding: 20px;
  margin: 20px 0;
  background-color: #ffebeb;
  color: #cc0000;
  border-radius: 8px;
}
</style>


// components/BuggyComponent.vue (A component designed to throw an error)
<template>
  <div class="buggy-component">
    <p>This component is about to throw an error.</p>
    <button @click="throwError">Click to trigger error</button>
  </div>
</template>

<script setup>
import { onMounted } from 'vue';

const throwError = () => {
  throw new Error('This is an intentional error from BuggyComponent!');
};

// Example of an error during a lifecycle hook
// onMounted(() => {
//   throw new Error('Error during BuggyComponent mounted hook!');
// });
</script>

<style scoped>
.buggy-component {
  border: 1px dashed blue;
  padding: 15px;
  margin: 10px 0;
}
</style>


// App.vue (Usage of ErrorBoundary)
<template>
  <h1>My Vue 3 App</h1>
  <p>Content above the error boundary.</p>

  <ErrorBoundary>
    <BuggyComponent />
    <p>This text is also within the ErrorBoundary slot.</p>
  </ErrorBoundary>

  <p>Content below the error boundary.</p>

  <button @click="throwGlobalError">Throw Global Error</button>
</template>

<script setup>
import ErrorBoundary from './components/ErrorBoundary.vue';
import BuggyComponent from './components/BuggyComponent.vue';

const throwGlobalError = () => {
  throw new Error('This error is thrown outside any ErrorBoundary!');
};
</script>
How it works: This snippet demonstrates two crucial aspects of error handling in Vue 3: a global error handler and component-level error boundaries. The `app.config.errorHandler` in `main.js` catches all uncaught errors bubbling up from components, providing a centralized point for logging or reporting. The `ErrorBoundary.vue` component utilizes the `onErrorCaptured` lifecycle hook, acting as a "catch-all" for errors originating from its child components (via slots). This allows isolating errors to specific parts of the UI, preventing the entire application from crashing and providing a graceful fallback UI.

Need help integrating this into your project?

Our team of expert developers can help you build your custom application from scratch.

Hire DigitalCodeLabs