Flare by Spatie
    • Error Tracking
    • Performance Monitoring
    • Logging Coming soon
  • Pricing
  • Docs
  • Insights
  • Changelog
  • Back to Flare ⌘↵ Shortcut: Command or Control Enter
  • Sign in
  • Try Flare for free
  • Error Tracking
  • Performance Monitoring
  • Logging Coming soon
  • Pricing
  • Docs
  • Insights
  • Changelog
    • Back to Flare ⌘↵ Shortcut: Command or Control Enter
    • Try Flare for free
    • Sign in
Flare Flare Laravel Laravel PHP PHP JavaScript JavaScript React React Vue Vue Protocol Protocol
  • General
  • Installation
  • Resolving bundled code
  • API reference
  • Errors
  • Error boundary
  • Error handling
  • Reporting errors
  • Client hooks
  • Data Collection
  • Adding custom context
  • Adding glows

Error boundary

The FlareErrorBoundary component uses Vue's onErrorCaptured hook to catch errors thrown by descendant components during setup, rendering, lifecycle hooks, watchers, and event handlers. When an error is caught, it is automatically reported to Flare with Vue-specific context including a structured component hierarchy.

Basic usage

Wrap your component tree (or parts of it) in the FlareErrorBoundary:

<script setup>
import { FlareErrorBoundary } from '@flareapp/vue';
</script>

<template>
    <FlareErrorBoundary>
        <MyComponent />
    </FlareErrorBoundary>
</template>

Without a fallback slot, the boundary renders nothing when an error is caught.

Displaying a fallback UI

The fallback slot is a scoped slot. Provide plain content for a static fallback:

<FlareErrorBoundary>
    <App />
    <template #fallback>
        <p>Something went wrong.</p>
    </template>
</FlareErrorBoundary>

Or use the slot props to render the error and let the user retry:

@verbatim
<FlareErrorBoundary>
    <App />
    <template #fallback="{ error, componentHierarchy, resetErrorBoundary }">
        <div>
            <h2>Something went wrong</h2>
            <p>{{ error.message }}</p>
            <pre>{{ componentHierarchy.join('\n') }}</pre>
            <button @click="resetErrorBoundary">Try again</button>
        </div>
    </template>
</FlareErrorBoundary>
@endverbatim

The fallback slot receives:

Slot prop Type Description
error Error The error that was caught.
componentHierarchy string[] Component names from the erroring component up to the app root.
componentHierarchyFrames ComponentHierarchyFrame[] Structured frames with component, file, and optional props.
componentProps Record<string, unknown> | undefined The erroring component's props. Only present when attachProps is enabled.
resetErrorBoundary () => void Clears the error state and re-renders the default slot.

Resetting the error boundary

You can automatically reset the boundary when certain values change using the resetKeys prop. When any value in the array changes (compared via Object.is), the boundary automatically resets and re-renders its children.

A common use case is resetting the boundary when the user navigates to a different page:

<script setup>
import { useRoute } from 'vue-router';
import { FlareErrorBoundary } from '@flareapp/vue';

const route = useRoute();
</script>

<template>
    <FlareErrorBoundary
        :reset-keys="[route.path]"
        :on-reset="(error) => {
            console.log('Navigated away from error, previous error:', error?.message);
        }"
    >
        <RouterView />
        <template #fallback>
            <p>Something went wrong.</p>
        </template>
    </FlareErrorBoundary>
</template>

The onReset callback fires when the boundary resets (either via resetErrorBoundary() from the fallback or via resetKeys changing). It receives the previous error, which lets you branch on what went wrong:

<script setup>
import { useQueryClient } from '@tanstack/vue-query';
import { FlareErrorBoundary } from '@flareapp/vue';

const queryClient = useQueryClient();
</script>

<template>
    <FlareErrorBoundary
        :on-reset="(error) => {
            console.log('Recovering from:', error?.message);
            queryClient.invalidateQueries();
        }"
    >
        <App />
        <template #fallback="{ resetErrorBoundary }">
            <button @click="resetErrorBoundary">Retry</button>
        </template>
    </FlareErrorBoundary>
</template>

Lifecycle hooks

The error boundary provides three hooks that fire at different stages of the error reporting lifecycle. All three callbacks receive { error, instance, info }, where instance is the Vue component that threw (or null) and info is Vue's lifecycle hook string (e.g. "setup function", "mounted hook", "component event handler").

The beforeSubmit and afterSubmit callbacks additionally receive a context object with the following shape:

{
    vue: {
        info: string;                        // Vue-provided lifecycle hook string
        errorOrigin: ErrorOrigin;            // Normalized category
        componentName: string;
        componentProps?: Record<string, unknown>;
        componentHierarchy: string[];
        componentHierarchyFrames: {
            component: string;
            file: string | null;
            props?: Record<string, unknown>;
        }[];
        route?: RouteContext;                // Present when Vue Router is detected
    }
}

These types are exported from @flareapp/vue as FlareVueContext and ComponentHierarchyFrame.

beforeEvaluate

Fires before the component hierarchy context is built. This is the place to attach custom context, tags, or user information to the Flare report:

<FlareErrorBoundary
    :before-evaluate="({ error, instance, info }) => {
        flare.addContext('user', { id: currentUser.id });
        flare.addContext('feature-flags', getActiveFlags());
    }"
>
    <App />
</FlareErrorBoundary>

beforeSubmit

Fires after the component hierarchy context is built but before the error is reported to Flare. The callback must return a (possibly modified) context object. Use this to filter or enrich the report context:

<FlareErrorBoundary
    :before-submit="({ error, instance, info, context }) => {
        return {
            ...context,
            vue: {
                ...context.vue,
                componentHierarchy: context.vue.componentHierarchy.filter(
                    (name) => name !== 'ThirdPartyWrapper',
                ),
            },
        };
    }"
>
    <App />
</FlareErrorBoundary>

afterSubmit

Fires after flare.report() is called. Note that the report is sent asynchronously, so this callback runs after the report is initiated, not after the network request completes. Use this for side effects like logging to a secondary service, showing a toast, or updating app state:

<FlareErrorBoundary
    :after-submit="({ error, instance, info, context }) => {
        console.error('Caught by FlareErrorBoundary:', error);
        console.error('Lifecycle info:', info);
        console.error('Reported context:', context);
    }"
>
    <App />
</FlareErrorBoundary>

Filtering errors

The boundary hooks above are designed for adding context and running side effects; they cannot prevent an error from being reported. To filter or suppress errors, use the core JavaScript client hooks via flare.configure().

Note that the boundary's beforeEvaluate and beforeSubmit are different hooks from flare.configure({ beforeEvaluate, beforeSubmit }) — they share the same name but have different signatures and capabilities. The execution order when both are configured is:

  1. Boundary beforeEvaluate (adds context, cannot suppress)
  2. flare.report() is called internally, which triggers:
  3. Client beforeEvaluate via flare.configure() (can suppress by returning false)
  4. Client beforeSubmit via flare.configure() (can suppress or modify the report)
  5. Report is sent to Flare
  6. Boundary afterSubmit

To suppress specific errors, use the client-level hooks:

flare.configure({
    beforeEvaluate: (error) => {
        if (error.message.includes('Boring error')) {
            return false; // Don't report this error
        }

        return error;
    },
});

See the client hooks documentation for more details.

Using your own error boundaries

If you have a component that already uses onErrorCaptured to render a custom fallback UI, the error won't bubble up to FlareErrorBoundary and won't be reported automatically. You can manually report errors to Flare from your own boundary:

<script setup>
import { onErrorCaptured, ref } from 'vue';
import { flare } from '@flareapp/js';

const error = ref(null);

onErrorCaptured((err) => {
    flare.report(err);
    error.value = err;
    return false;
});
</script>

You can also combine Flare's boundary at the root of your app with your own boundaries further down the tree for specific sections.

Capturing component props

Vue's onErrorCaptured gives the boundary access to the live component instance. You can capture the erroring component's props by enabling attachProps:

<FlareErrorBoundary :attach-props="true">
    <App />
</FlareErrorBoundary>

When enabled, props are attached both at context.vue.componentProps (the erroring component's props) and per-frame on context.vue.componentHierarchyFrames (each frame's own props).

Props capture is opt-in because props may contain sensitive data. Values are serialized with the following rules:

  • Functions become "[Function]", symbols become "[Symbol]", bigints are converted to strings, circular references become "[Circular]", class instances, Date, RegExp, Map, Set, etc. become "[Object]".
  • Symbol-keyed properties are dropped.
  • Strings longer than 1000 characters are truncated, with a "…[truncated N chars]" suffix appended.
  • Arrays longer than 100 items are trimmed, with a final "[… N more items]" entry appended.
  • Objects with more than 100 keys are trimmed, with an extra "…": "[N more keys]" entry appended.

You can control serialization with two additional props:

Prop Default Description
propsMaxDepth 2 How deep nested objects and arrays are serialized before collapsing to "[Object]" / "[Array]".
propsDenylist DEFAULT_PROPS_DENYLIST A RegExp tested against each key at every depth. Matching keys are replaced with "[redacted]". By default, a custom value is merged with the built-in denylist (both patterns apply). Set replaceDefaultDenylist to true to use only your custom pattern.

The default denylist covers common sensitive terms (password, token, secret, authorization, cookie, api_key, session, csrf, ssn, card_number, cvv, …). Since custom denylists extend the default automatically, you can simply pass additional patterns:

<FlareErrorBoundary :attach-props="true" :props-denylist="/internalId/i">
    <App />
</FlareErrorBoundary>

If you need to replace the default entirely (e.g. it matches too aggressively for your use case), pass :replace-default-denylist="true":

<FlareErrorBoundary
    :attach-props="true"
    :props-denylist="/myCustomPattern/i"
    :replace-default-denylist="true"
>
    <App />
</FlareErrorBoundary>

Component hierarchy context

When the error boundary catches an error, it walks the $parent chain of the erroring component and sends both a flat string array and structured frames in the report context:

{
  "context": {
    "vue": {
      "info": "setup function",
      "errorOrigin": "setup",
      "componentName": "BuggyComponent",
      "componentHierarchy": [
        "BuggyComponent",
        "ParentPage",
        "AppLayout",
        "App"
      ],
      "componentHierarchyFrames": [
        { "component": "BuggyComponent", "file": "src/components/BuggyComponent.vue" },
        { "component": "ParentPage", "file": "src/pages/ParentPage.vue" },
        { "component": "AppLayout", "file": "src/layouts/AppLayout.vue" },
        { "component": "App", "file": "src/App.vue" }
      ]
    }
  }
}

The structured frames enable rich dashboard rendering and sourcemap resolution.

A few notes:

  • Component names are read from $options.__name (set by the SFC compiler for <script setup>) or $options.name, falling back to "AnonymousComponent".
  • The file field comes from $options.__file and is only available in development builds. It is null in production.
  • Traversal stops at the app root (where $parent is null) and is bounded at 50 entries as a safety net against pathological parent chains.

Error origin

Vue's info string describes where the error was caught. The boundary also includes a normalized errorOrigin category, which is easier to filter and group on:

errorOrigin Example info strings
setup setup function, ref function, async component loader
render render function, component update, scheduler flush
lifecycle mounted hook, beforeUnmount hook, updated hook, directive hook, …
event native event handler, component event handler
watcher watcher getter, watcher callback, watcher cleanup function
unknown Anything Vue emits that doesn't map to the above

Both development strings and production single-letter codes are mapped.

Vue Router context

If Vue Router is installed on the app, the boundary automatically detects it via app.config.globalProperties.$router and includes the current route in the report context. No configuration required.

{
  "context": {
    "vue": {
      "route": {
        "name": "user-profile",
        "path": "/users/42",
        "fullPath": "/users/42?tab=settings",
        "params": { "id": "42" },
        "query": { "tab": "settings" },
        "hash": "",
        "matched": ["AppLayout", "UserProfile"]
      }
    }
  }
}

Route params and query are serialized with the same denylist as componentProps, so values keyed with sensitive names (e.g. token) are redacted.

The route's fullPath is also passed through URL redaction (using the same logic as url.full), so sensitive query-string values are redacted before being included in the report.

Using the boundary with flareVue()

FlareErrorBoundary returns false from onErrorCaptured, which stops the error from propagating to app.config.errorHandler. When you use both the boundary and the flareVue plugin, errors caught by the boundary are reported to Flare exactly once — using the boundary's hooks and options. The plugin's hooks only fire for errors that are not caught by a boundary. Errors outside any boundary are still caught by the plugin.

Props reference

Prop Type Description
resetKeys unknown[] Values that trigger an automatic reset when changed (compared via Object.is).
onReset (error: Error | null) => void Called when the boundary is reset; receives the previous error.
beforeEvaluate ({ error, instance, info }) => void Called before the component hierarchy context is built.
beforeSubmit ({ error, instance, info, context }) => FlareVueContext Called before submitting; must return a (possibly modified) context.
afterSubmit ({ error, instance, info, context }) => void Called after flare.report() is called (the report is sent asynchronously).
attachProps boolean (default false) Attach the erroring component's props, plus each frame's props, to the report context.
propsMaxDepth number (default 2) Depth limit used when serializing props.
propsDenylist RegExp (default DEFAULT_PROPS_DENYLIST) Keys matching this expression are redacted at every depth.
replaceDefaultDenylist boolean (default false) When true, propsDenylist replaces the built-in denylist instead of extending it.
API reference Error handling
  • On this page
  • Basic usage
  • Displaying a fallback UI
  • Resetting the error boundary
  • Lifecycle hooks
  • Filtering errors
  • Using your own error boundaries
  • Capturing component props
  • Component hierarchy context
  • Error origin
  • Vue Router context
  • Using the boundary with
  • Props reference

Catch errors and fix slowdowns with Flare, the full-stack application monitoring platform for Laravel, PHP & JavaScript.

  • Platform
  • Error Tracking
  • Performance Monitoring
  • Pricing
  • Support
  • Resources
  • Insights
  • Newsletter
  • Changelog
  • Documentation
  • Affiliate program
  • uptime status badge Service status
  • Terms of use
  • DPA
  • Privacy & cookie Policy
Made in by
Flare