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
| Method | Scope | Use Case |
|---|---|---|
try/catch | Current function | Async operations, API calls |
onErrorCaptured | Descendant components | Error boundaries |
app.config.errorHandler | Entire app | Global logging, Sentry |
app.config.warnHandler | Entire 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 readyPremium
A concise answer to help you respond confidently on this topic during an interview.