Skip to main content
Practice Problems

Error handling in Vue.js

Error Handling in Vue.js

Vue provides several mechanisms for catching and handling errors: the onErrorCaptured hook, global error handlers, and error boundaries using component patterns.


onErrorCaptured Hook

Catches errors from descendant components:

vue
<script setup> import { ref, onErrorCaptured } from 'vue' const error = ref<Error | null>(null) onErrorCaptured((err, instance, info) => { error.value = err as Error console.error('Captured error:', err) console.log('Component:', instance) console.log('Info:', info) // e.g., "setup function", "render" return false // Stop error propagation }) </script> <template> <div v-if="error" class="error-boundary"> <h2>Something went wrong</h2> <p>{{ error.message }}</p> <button @click="error = null">Try Again</button> </div> <slot v-else /> </template>

Error Boundary Component

vue
<!-- ErrorBoundary.vue --> <script setup> import { ref, onErrorCaptured } from 'vue' const error = ref<Error | null>(null) const errorInfo = ref('') onErrorCaptured((err, instance, info) => { error.value = err as Error errorInfo.value = info return false }) function retry() { error.value = null } </script> <template> <div v-if="error" class="error-fallback"> <h3>Error: {{ error.message }}</h3> <p>Occurred in: {{ errorInfo }}</p> <button @click="retry">Retry</button> </div> <slot v-else /> </template>
vue
<!-- Usage --> <template> <ErrorBoundary> <DangerousComponent /> </ErrorBoundary> </template>

Global Error Handler

typescript
// main.ts const app = createApp(App) app.config.errorHandler = (err, instance, info) => { // Log to external service (Sentry, etc.) console.error('Global error:', err) console.log('Component:', instance) console.log('Info:', info) // Send to error tracking service Sentry.captureException(err) }

Global Warning Handler (Development)

typescript
app.config.warnHandler = (msg, instance, trace) => { console.warn('Vue warning:', msg) console.log('Trace:', trace) }

Async Error Handling

vue
<script setup> import { ref } from 'vue' const data = ref(null) const error = ref<Error | null>(null) const loading = ref(false) async function fetchData() { loading.value = true error.value = null try { const response = await fetch('/api/data') if (!response.ok) throw new Error(`HTTP ${response.status}`) data.value = await response.json() } catch (e) { error.value = e as Error } finally { loading.value = false } } </script> <template> <div v-if="loading">Loading...</div> <div v-else-if="error" class="error"> <p>{{ error.message }}</p> <button @click="fetchData">Retry</button> </div> <div v-else>{{ data }}</div> </template>

Error Propagation

Component Error onErrorCaptured (parent) ← can stop with return false ↓ (if not stopped) onErrorCaptured (grandparent) ↓ (if not stopped) app.config.errorHandler (global)

Summary

MethodScopeUse Case
try/catchCurrent functionAsync operations, API calls
onErrorCapturedDescendant componentsError boundaries
app.config.errorHandlerEntire appGlobal logging, Sentry
app.config.warnHandlerEntire app (dev)Development warnings

Important:

Vue errors propagate up the component tree via onErrorCaptured. Create reusable Error Boundary components to catch and display errors gracefully. Always set a global error handler (app.config.errorHandler) for logging to services like Sentry. Use try/catch for async operations within components.

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.

Finished reading?
Practice Problems