Production-ready error boundaries for Vue 3 — a declarative component, a composable for programmatic use, and an adapter-based reporting layer.

One unhandled throw deep in the component tree turns the whole app into a blank screen for the user — vue-error-boundary-kit limits the blast radius to a single widget instead of the entire page.
Wrap a product card, a comment section, or a dashboard widget in its own protective boundary — if it crashes, the widgets around it keep working instead of turning into the same blank screen.
A component's own error handling structurally can't see exceptions from click handlers, timers, or unhandled promise rejections — those need a separate, global catch.
A flaky network request deserves a delayed retry, while a logic error deserves being surfaced to the user and stopped right away. The boundary can be configured to tell the two apart on its own, instead of blindly retrying something that was never going to succeed.
Pluggable adapters send errors to Sentry, Bugsnag, or your own HTTP endpoint, and a built-in DevTools history shows what broke before a user has to file a ticket about it.

Wrap any part of your app in <ErrorBoundary> with a fallback slot for error display. Control state via resetKeys, maxRetries, and auto-reset on prop changes. Access error, reset/retry methods, and retry count both in the slot and via a template ref.

Use useErrorBoundary() to manually register errors from any code — e.g., when parsing JSON or in event handlers. And with useGlobalErrorCapture(), catch unhandled errors and promise rejections that Vue cannot see.

Send errors to Sentry, Bugsnag, LogRocket, an HTTP endpoint, or the console via pluggable adapters. Each adapter is a separate entry point, not bloating the main bundle. Built‑in rate limiting and breadcrumbs protect against spam and provide context.

The Nuxt module auto-registers the component and utilities. useNuxtErrorBoundary() catches app‑level errors, while useRouterErrorBoundary() catches navigation and async route errors. For TanStack Query, a dedicated hook resets errored queries.

AsyncBoundary combines Suspense and ErrorBoundary with a unified API and loading/fallback slots. For debugging, use the error history and a devtools panel. All components are SSR‑safe — render errors never crash the server, and hydration always converges to the correct state.

Specify shouldCatch so a boundary only catches the error types you care about, letting everything else propagate up the tree — this lets you nest boundaries with different areas of responsibility. Automatic retry with exponential backoff re‑runs the operation after a failure.
Wrap part of the tree in <ErrorBoundary> — on failure the fallback slot renders, and resetKeys resets the boundary automatically when the route changes.
<script setup lang="ts">
import { ErrorBoundary } from 'vue-error-boundary-kit'
import UserProfile from './UserProfile.vue'
const userId = ref('42')
const routeId = ref('profile')
function handleError(error) {
// error: CapturedError — see Types below
}
</script>
<template>
<ErrorBoundary :reset-keys="[routeId]" @error="handleError">
<template #default>
<UserProfile :id="userId" />
</template>
<template #fallback="{ error, reset, retryCount }">
<ErrorState :message="error.message" @retry="reset" />
</template>
</ErrorBoundary>
</template>useErrorBoundary() catches what errorCaptured simply can't see — an error thrown inside an event handler, say, or while parsing untrusted data.
import { useErrorBoundary } from 'vue-error-boundary-kit'
const { error, hasError, reset, captureError } = useErrorBoundary({
onError: (e) => report(e),
reporter: myReporter,
})
try {
JSON.parse(untrustedInput)
} catch (err) {
captureError(err, { source: 'manual', componentName: 'ImportPanel' })
}createRateLimitedReporter wraps any reporters and caps duplicates and bursts on its own — a broken list re-rendering hundreds of times a second won't flood Sentry with near-identical events.
import { createSentryReporter } from 'vue-error-boundary-kit/adapters/sentry'
import { createRateLimitedReporter } from 'vue-error-boundary-kit/adapters/rate-limit'
const sentryReporter = createSentryReporter({ client: sentryClient })
const reporter = createRateLimitedReporter([sentryReporter], {
maxPerWindow: 10, // at most 10 reports forwarded per 10s window
dedupWindowMs: 10_000, // suppress identical repeats within this window
})
// Pass `reporter` to <ErrorBoundary>, useErrorBoundary(), or
// useGlobalErrorCapture() — it composes with everything else, same as any
// other ErrorReporter.