# Error handling


The `flareVue` plugin hooks into Vue's `app.config.errorHandler` to automatically catch and report component errors to Flare. This page explains what context is collected, how to customize the reporting lifecycle, and how to opt in to Vue-specific features like component prop capture, warning capture, and route context.

If you want to render a fallback UI and allow users to recover from errors, see the [`FlareErrorBoundary`](/docs/vue/errors/error-boundary) docs. The two are designed to be used together.

## Automatic error handling

When a Vue component throws an error, the plugin:

1. Converts the thrown value to an `Error` (if it isn't one already),
2. Builds a Vue-specific context (see below),
3. Reports the error to Flare,
4. Calls any previously registered error handler (chaining),
5. Re-throws the error if no previous error handler was registered.

## Vue context

Each error report includes Vue-specific context under the `vue` key:

```json
{
    "vue": {
        "info": "setup function",
        "errorOrigin": "setup",
        "componentName": "CheckoutForm",
        "componentHierarchy": [
            "CheckoutForm",
            "CheckoutPage",
            "AppLayout",
            "App"
        ],
        "componentHierarchyFrames": [
            { "component": "CheckoutForm", "file": "src/components/CheckoutForm.vue" },
            { "component": "CheckoutPage", "file": "src/pages/CheckoutPage.vue" },
            { "component": "AppLayout", "file": "src/layouts/AppLayout.vue" },
            { "component": "App", "file": "src/App.vue" }
        ]
    }
}
```

- **`info`** - The Vue-provided string describing where the error was caught (e.g. `"setup function"`, `"mounted hook"`, `"component event handler"`).
- **`errorOrigin`** - A normalized category derived from `info`: `"setup"`, `"render"`, `"lifecycle"`, `"event"`, `"watcher"`, or `"unknown"`. See [Error origin](/docs/vue/errors/error-boundary#error-origin) for the full mapping.
- **`componentName`** - The name of the component that threw (read from `$options.__name` or `$options.name`, falling back to `"AnonymousComponent"`).
- **`componentHierarchy`** - Component names walked up the `$parent` chain from the erroring component to the app root.
- **`componentHierarchyFrames`** - Structured frames with `component`, `file` (only in development builds), and optional `props`.

Optional fields `componentProps` and `route` are added when the corresponding features are enabled (see below).

## Lifecycle hooks

The `flareVue` plugin accepts an options object that lets you hook into 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.

```ts
import { flare } from '@flareapp/js';
import { flareVue } from '@flareapp/vue';
import { createApp } from 'vue';

const app = createApp(App);

app.use(flareVue, {
    beforeEvaluate: ({ error, instance, info }) => {
        flare.addContext('user', { id: currentUser.id });
    },
    beforeSubmit: ({ error, instance, info, context }) => {
        return {
            ...context,
            vue: {
                ...context.vue,
                customField: 'value',
            },
        };
    },
    afterSubmit: ({ error, instance, info, context }) => {
        console.error('Error reported to Flare:', error.message);
    },
});
```

The three hooks fire in this order:

1. **`beforeEvaluate`** - called after the error is caught, before building the component hierarchy context. Use this to attach custom context to Flare (e.g. user info, feature flags).
2. **`beforeSubmit`** - called with the built context, must return a (possibly modified) context object. Use this to filter or enrich the report context before it is sent.
3. **`flare.report()`** - the error is reported to Flare.
4. **`afterSubmit`** - called after the report is initiated. Note that the report is sent asynchronously, so this callback runs before the network request completes. Use this for side effects like logging or showing a toast.

The `FlareVueContext` type is exported from `@flareapp/vue` so you can type your callbacks strictly.

## Filtering errors

The lifecycle 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 plugin'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. Plugin `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. Plugin `afterSubmit`

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

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

        return error;
    },
});
```

You can also modify the report before it's sent:

```js
flare.configure({
    beforeSubmit: (report) => {
        const editedReport = structuredClone(report);

        // Strip sensitive data
        editedReport.attributes['user_agent.original'] = null;

        return editedReport;
    },
});
```

See the [client hooks documentation](/docs/javascript/errors/client-hooks) for more details.

## Chaining with existing error handlers

If you have a custom `app.config.errorHandler` set up before registering `flareVue`, the plugin will call your handler after reporting the error to Flare:

```js
import { flare } from '@flareapp/js';
import { flareVue } from '@flareapp/vue';
import { createApp } from 'vue';

const app = createApp({ /* … */ });

// Your custom error handler - will still be called
app.config.errorHandler = (error, instance, info) => {
    console.error('Custom handler:', error);
};

flare.light('YOUR PROJECT KEY');

// flareVue will report to Flare AND call your handler above
app.use(flareVue);

app.mount('#app');
```

Note that the report is sent asynchronously, so your handler runs before the network request completes.

## Capturing component props

Vue gives us the live component instance when an error occurs, so we can read the erroring component's props directly. This is opt-in because props may contain sensitive data.

```ts
app.use(flareVue, {
    attachProps: true,
});
```

When enabled, props are attached at `context.vue.componentProps` (the erroring component's props) and per-frame on `context.vue.componentHierarchyFrames` (each frame gets its own props). Values are serialized with the same redaction rules as the error boundary. See [Capturing component props](/docs/vue/errors/error-boundary#capturing-component-props) for the full description of the serializer, `propsMaxDepth`, `propsDenylist`, and the exported `DEFAULT_PROPS_DENYLIST`.

```ts
import { DEFAULT_PROPS_DENYLIST, flareVue } from '@flareapp/vue';

app.use(flareVue, {
    attachProps: true,
    propsMaxDepth: 3,
    propsDenylist: new RegExp(`${DEFAULT_PROPS_DENYLIST.source}|internalId`, 'i'),
});
```

## Capturing Vue warnings

Vue's `app.config.warnHandler` fires for runtime warnings in development builds (invalid prop types, missing required props, mutating props directly, and similar issues). These warnings often indicate bugs that will eventually become errors. Enable `captureWarnings` to report them to Flare as non-fatal messages:

```ts
app.use(flareVue, {
    captureWarnings: true,
});
```

Warnings are reported via `flare.reportMessage()` with level `'warning'`. The context looks like:

```json
{
    "vue": {
        "type": "warning",
        "info": "Invalid prop: type check failed for prop \"count\". Expected Number, got String.",
        "componentName": "Counter",
        "componentTrace": "found in\n---> <Counter> at src/Counter.vue\n       <App> at src/App.vue"
    }
}
```

**`app.config.warnHandler` only fires in development mode.** Vue compiles warnings out of production builds, so this feature is primarily useful during development and staging where you're running development builds. Warnings reported this way use `flare.reportMessage()` and count toward your quota like any other report.

If you already have a custom `warnHandler` set up, the plugin chains onto it the same way it chains onto `errorHandler`.

## Vue Router context

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

```json
{
    "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` values are always redacted using the props denylist (or `DEFAULT_PROPS_DENYLIST` if none is configured), regardless of whether `attachProps` is enabled. The denylist controls which **keys** are considered sensitive, and it applies to both props and route data independently. For example, a route param named `token` will be redacted even when `attachProps` is `false`.

The route's `fullPath` is also redacted for sensitive query-string values before being included in the report.

## Using `flareVue()` alongside `FlareErrorBoundary`

The [`FlareErrorBoundary`](/docs/vue/errors/error-boundary) component uses `onErrorCaptured` and returns `false`, which stops the error from propagating to `app.config.errorHandler`. When you use both, errors caught by a boundary are reported to Flare exactly once. Errors thrown outside any boundary are still caught by the plugin.

When both are used, errors caught by a boundary use the **boundary's** hooks and options (`attachProps`, `propsMaxDepth`, `propsDenylist`). The plugin's hooks only fire for errors that are **not** caught by a boundary.

A typical setup reports every error via the plugin and uses the boundary at the root (or in specific sections) to display a fallback UI:

```js
import { flare } from '@flareapp/js';
import { flareVue } from '@flareapp/vue';
import { createApp } from 'vue';
import App from './App.vue';

flare.light('YOUR PROJECT KEY');

const app = createApp(App);
app.use(flareVue);
app.mount('#app');
```

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

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

## Options reference

| Option | Type | Default                  | Description                                                                                              |
|--------|------|--------------------------|----------------------------------------------------------------------------------------------------------|
| `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` | `false`                  | Attach the erroring component's props, plus each frame's props, to the report context.                   |
| `propsMaxDepth` | `number` | `2`                      | Depth limit used when serializing props.                                                                 |
| `propsDenylist` | `RegExp` | `DEFAULT_PROPS_DENYLIST` | Keys matching this expression are redacted at every depth.                                               |
| `replaceDefaultDenylist` | `boolean` | `false` | When `true`, `propsDenylist` replaces the built-in denylist instead of extending it. |
| `captureWarnings` | `boolean` | `false`                  | Hook into `app.config.warnHandler` to report Vue warnings via `flare.reportMessage()`. Development-only. |
