ErrorBoundary
Props
resetKeys
unknown[] · default: —
When any value changes (compared with Object.is), the boundary auto-resets — same idea as react-error-boundary's resetKeys.
resetOnPropsChange
boolean · default: false
Reset whenever any prop reference changes, not just resetKeys.
beforeReset
() => void · default: —
Called right before a reset (auto or manual). Not named onReset — see note below.
isolate
boolean · default: true
false lets the error also propagate to the nearest ancestor <ErrorBoundary>.
maxRetries
number · default: unlimited
Once reached, the fallback slot's canRetry becomes false.
reporter
ErrorReporter | ErrorReporter[] · default: —
Reporter(s) invoked once per captured error — see Reporting adapters.
shouldCatch
(error: CapturedError) => boolean · default: —
Return false to let an error pass through this boundary untouched — no state change, no report, no fallback — exactly as if it weren't there. See Ignoring specific errors.
internalErrorPrefix
string · default: '[vue-error-boundary-kit]'
Prefix for the safety-net log emitted when your own beforeReset/reporter itself throws. Pass '' to omit it.
Why
beforeReset, notonReset? This component also emits aresetevent, and Vue derivesonResetas that event's own listener prop. A declared prop with the identical name would collide with it: Vue'semit()looks upprops.onResetindependently of whether it's "really" a declared prop, so it would've fired twice per reset — and the second, emit-triggered call happens outside this package's own try/catch, defeating the recursion guard entirely if it throws.beforeResetavoids the collision structurally.
Events
error
(error: CapturedError)
Fired for every captured failure, including ones bubbled up from a descendant boundary with isolate: false.
reset
Fired on every manual or automatic reset.
Slots
default
Normal content.
fallback
{ error, reset, retry, retryCount, canRetry }
reset() clears retry count too; retry() increments retryCount and re-attempts default without resetting the count.
Exposed
Via a template ref: error, hasError, retryCount, canRetry, reset(), retry() — the same state and methods the fallback slot gets, but reachable from outside it (e.g. a retry control that lives elsewhere in the UI, or an ancestor recovering a boundary it doesn't render the fallback for). Calling reset()/retry() on a boundary that isn't in an error state is a harmless no-op.
<script setup>
const boundary = ref()
</script>
<template>
<ErrorBoundary ref="boundary">…</ErrorBoundary>
<button @click="boundary?.reset()">Reset from elsewhere</button>
</template>Retry with backoff
retry() is instant and unconditional — fine for most cases, but for a transient/network-ish failure, retrying the instant the button is clicked usually just fails again the same way. vue-error-boundary-kit/retry-backoff wraps a template ref's retry() with an increasing delay instead:
import { createBackoffRetry } from 'vue-error-boundary-kit/retry-backoff'
const boundary = useTemplateRef('boundary')
const backoff = createBackoffRetry(boundary, { baseDelayMs: 1000, factor: 2, maxDelayMs: 30_000 })<ErrorBoundary ref="boundary">
<template #fallback="{ error }">
<button :disabled="backoff.isPending.value" @click="backoff.retry()">
{{ backoff.isPending.value ? 'Retrying…' : 'Retry' }}
</button>
</template>
</ErrorBoundary>The delay is computed from the boundary's own retryCount (baseDelayMs * factor ** retryCount, capped at maxDelayMs), so each successive attempt waits longer. cancel() clears a pending retry. Works with <AsyncBoundary>'s ref too — both expose the same { retry, retryCount } shape.
AsyncBoundary
Separate entry point (vue-error-boundary-kit/async-boundary) — not part of the core bundle, so it costs nothing if you don't import it. Combines <Suspense> and <ErrorBoundary>, which today you'd otherwise nest by hand:
import { AsyncBoundary } from 'vue-error-boundary-kit/async-boundary'<AsyncBoundary :reset-keys="[userId]">
<template #default>
<UserProfile :id="userId" />
<!-- async setup() / async components allowed -->
</template>
<template #loading>
<Spinner />
</template>
<template #fallback="{ error, retry }">
<ErrorState :message="error.message" @retry="retry" />
</template>
</AsyncBoundary>It's a composition, not a reimplementation: internally it's <ErrorBoundary> wrapping a <Suspense>, so it accepts every <ErrorBoundary> prop (resetKeys, maxRetries, reporter, shouldCatch, …) documented above, emits the same error/reset events, and exposes the same error/hasError/retryCount/canRetry/reset()/retry() via a template ref — all handled by the one onErrorCaptured implementation <ErrorBoundary> already has. The only thing it adds is the loading slot, rendered while the default slot's async dependencies are pending. retry()/reset() remount the default slot, so a retried async operation genuinely re-runs (the loading slot reappears while it does) rather than just re-showing stale state.