Tutorials Logic, IN info@tutorialslogic.com

Vue Error Handling onErrorCaptured Global Handler: Causes and Fixes

Vue Failure Boundaries

Expected failures such as rejected requests belong in feature state with retry or fallback UI. Unexpected render, setup, watcher, lifecycle, directive, transition, and event errors flow through Vue error capture and finally the application handler.

Recovery and reporting are separate decisions: preserve a usable interface locally and send sanitized diagnostic context to one reporting boundary.

Failure Ownership

Classify the failure before choosing an API. A validation response, cancellation, offline request, and empty result are feature outcomes; a render exception or watcher defect belongs to Vue error capture.

Failure Owner Response
Request or validation result Feature composable or store Loading, error, retry, or correction state.
Descendant render or lifecycle error Nearest component boundary Replace only the failed region.
Unhandled Vue application error app.config.errorHandler Report sanitized context.
Script failure outside Vue Browser monitoring boundary Record only application-owned code.

Async Feature State

fetch resolves for HTTP error statuses, so check response.ok. Treat AbortError as cancellation, cancel obsolete requests, and prevent a stale response from replacing newer state.

Retryable Request

Retryable Request
const data = ref(null);
const error = ref("");
const loading = ref(false);
let controller: AbortController | undefined;

async function load() {
  controller?.abort();
  controller = new AbortController();
  loading.value = true;
  error.value = "";

  try {
    const response = await fetch("/api/profile", {
      signal: controller.signal
    });
    if (!response.ok) {
      throw new Error("Request failed: " + response.status);
    }
    data.value = await response.json();
  } catch (cause) {
    if (cause instanceof DOMException &&
        cause.name === "AbortError") return;
    error.value = "Profile could not be loaded.";
  } finally {
    loading.value = false;
  }
}

onBeforeUnmount(() => controller?.abort());

The feature owns expected request state and never renders raw server details.

Component Boundaries

onErrorCaptured observes errors from descendants and receives the error, component instance, and source information. Returning false stops propagation, so use it only when the boundary renders a deliberate fallback and records the failure.

Retrying must recreate the failed child or provide different input; merely hiding the fallback does not repair a broken instance.

Descendant Error Boundary

Descendant Error Boundary
<script setup>
import { onErrorCaptured, ref } from "vue";

const failed = ref(false);
const retryKey = ref(0);

onErrorCaptured((error, instance, info) => {
  failed.value = true;
  reportError({ error, info });
  return false;
});

function retry() {
  failed.value = false;
  retryKey.value += 1;
}
</script>

<template>
  <section v-if="failed" role="alert">
    <p>This widget could not be displayed.</p>
    <button @click="retry">Try again</button>
  </section>
  <slot v-else :key="retryKey" />
</template>

The boundary preserves the rest of the page and deliberately stops propagation after reporting.

Global Reporting

app.config.errorHandler receives uncaught application errors, a component instance when available, and Vue source information. Production may provide a shortened source code, so store the release and Vue version with each event.

Do not throw from the reporter or expose props, tokens, request bodies, or personal data. Deduplicate repeated failures and keep user messaging at the owning feature boundary.

Application Error Handler

Application Error Handler
app.config.errorHandler = (error, instance, info) => {
  try {
    reportError({
      message: error instanceof Error
        ? error.message
        : "Unknown Vue error",
      component: instance?.$options.name ?? "anonymous",
      source: info,
      release: import.meta.env.VITE_RELEASE
    });
  } catch {
    console.error("Error reporting failed");
  }
};

The handler reports unexpected defects; it does not replace local loading and retry state.

Async Components

An async component loader can fail because a chunk is missing, a deployment replaced old assets, or the network is unavailable. Define loading, error, delay, timeout, and a controlled retry policy with defineAsyncComponent.

Suspense coordinates pending async dependencies but does not provide its own error handling. Capture rejected async setup from an ancestor boundary.

Debugging Workflow

  • Reproduce with the smallest route, props, and action.
  • Read the first error and component trace before secondary failures.
  • Classify render, setup, watcher, event, lifecycle, directive, transition, or loader ownership.
  • Test the fallback and reporting path by making a child fail deliberately.
  • Verify protected source maps and release identifiers in production.
Before you move on

Failure Review

5 checks
  • Expected failures have loading, error, retry, and cancellation states.
  • A component boundary replaces only the region it owns.
  • Returning false from onErrorCaptured is deliberate.
  • Global reporting redacts sensitive data.
  • Async component failures have a recovery policy.

Error Handling Failures

  • Raw error reaches the user

    Show a safe action-oriented message and protect technical details.
  • Every error is swallowed

    Recover expected outcomes locally and report unexpected defects.
  • Stale retry wins

    Cancel obsolete work and let only the latest request update state.

Try this next

Test Vue Failures

0 of 2 completed

  1. Make a child throw during rendering and assert fallback plus reporting. Test propagation with and without returning false.
  2. Prove that an aborted request neither displays an error nor overwrites a newer result. Use AbortController.

Vue Error Questions

It captures descendant errors, so place the boundary above the component that may fail.

Suspense coordinates pending state but does not provide its own error handling.

Vue warnings are development-only. Fix them during development instead of treating them as production reporting.

Browse Free Tutorials

Explore 500+ free tutorials across 20+ languages and frameworks.