Skip to content

Error Boundary Kit

v0.3.5DX & ReliabilityVueNuxt

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

Error Boundary Kit
Get started →
npm install vue-error-boundary-kit@latest
01 — Purpose

When you'd reach for this

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.

A single broken widget shouldn't take down the 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.

The error happens outside render, not inside it

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.

Not every error deserves the same response

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.

Errors shouldn't only live in the dev console

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.

02 — Features

At a glance

Declarative ErrorBoundary component

Declarative ErrorBoundary component

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.

Programmatic capture and global monitoring

Programmatic capture and global monitoring

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.

Flexible reporting system with adapters

Flexible reporting system with adapters

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.

Ready-to-use integration with Nuxt, vue-router, and TanStack Query

Ready-to-use integration with Nuxt, vue-router, and TanStack Query

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, error history, and SSR safety

AsyncBoundary, error history, and SSR safety

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.

Precise error filtering and retry with backoff

Precise error filtering and retry with backoff

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.

03 — Quick example

See how it works

A declarative error boundary

Wrap part of the tree in <ErrorBoundary> — on failure the fallback slot renders, and resetKeys resets the boundary automatically when the route changes.

App.vue
<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>

Manual capture outside a template

useErrorBoundary() catches what errorCaptured simply can't see — an error thrown inside an event handler, say, or while parsing untrusted data.

manual-capture.ts
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' })
}

Protection from a storm of identical error reports

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.

reporting.ts
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.