Frontend Development 15 min read

Understanding Vue.js Error Handling and Source Code Analysis

This article explains Vue's error handling mechanisms—including global errorHandler, component-level errorCaptured, and the underlying source code functions handleError, invokeWithErrorHandling, globalHandleError, and logError—through detailed code examples, execution flow diagrams, and practical interview scenarios.

Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Understanding Vue.js Error Handling and Source Code Analysis

The article begins with an interview anecdote where a candidate is asked about Vue's error handling and then dives into a systematic exploration of Vue's error capture mechanisms.

1. Recognizing Vue Error Handling

errorHandler

Vue provides a global errorHandler that can be set in main.js . The article shows a minimal example:

// main.js
Vue.config.errorHandler = function (err, vm, info) {
  console.log('全局捕获 err >>>', err)
  console.log('全局捕获 vm >>>', vm)
  console.log('全局捕获 info >>>', info)
}

// App.vue
created() {
  const obj = {}
  // Directly invoke a non‑existent function to trigger an error
  obj.fn()
},
methods: {
  handleClick() {
    const obj = {}
    obj.fn()
  }
}

Running this code logs the error information from the created hook and the click handler, illustrating how errorHandler receives err , vm , and info .

errorCaptured

The component‑level errorCaptured hook can catch errors from descendant components. The article provides a template that includes a HelloWorld child component and demonstrates that both errorCaptured and the global errorHandler receive the same error, similar to event bubbling.

It also notes that errorCaptured does not fire for errors originating in the component itself, only for its descendants. An experiment adds errorCaptured to the child component and logs an additional message, confirming this behavior.

2. Vue Error‑Capture Source Code

The source examined is Vue v2.6.14, located in src/core/util/error.js . Four core functions are discussed:

handleError : the unified error‑handling entry point that traverses the component tree via $parent , invokes each component’s errorCaptured hooks, and finally calls the global errorHandler .

invokeWithErrorHandling : a higher‑order wrapper that executes a given handler inside a try‑catch block, also handling Promise rejections and delegating caught errors to handleError .

globalHandleError : invokes the user‑defined global errorHandler and, if that throws, logs the secondary error via logError .

logError : prints error details; in development it uses warn (which prefixes messages with [Vue warn]: ) and console.error , while in production it may re‑throw.

Key snippets:

function handleError (err, vm, info) {
  pushTarget()
  try {
    if (vm) {
      let cur = vm
      while ((cur = cur.$parent)) {
        const hooks = cur.$options.errorCaptured
        if (hooks) {
          for (let i = 0; i < hooks.length; i++) {
            try {
              const capture = hooks[i].call(cur, err, vm, info) === false
              if (capture) return
            } catch (e) {
              globalHandleError(e, cur, 'errorCaptured hook')
            }
          }
        }
      }
    }
    globalHandleError(err, vm, info)
  } finally {
    popTarget()
  }
}

function invokeWithErrorHandling(handler, context, args, vm, info) {
  let res
  try {
    res = args ? handler.apply(context, args) : handler.call(context)
    if (res && !res._isVue && isPromise(res) && !res._handled) {
      res.catch(e => handleError(e, vm, info + ` (Promise/async)`))
      res._handled = true
    }
  } catch (e) {
    handleError(e, vm, info)
  }
  return res
}

function globalHandleError(err, vm, info) {
  if (config.errorHandler) {
    try {
      return config.errorHandler.call(null, err, vm, info)
    } catch (e) {
      if (e !== err) {
        logError(e, null, 'config.errorHandler')
      }
    }
  }
  logError(err, vm, info)
}

function logError(err, vm, info) {
  if (process.env.NODE_ENV !== 'production') {
    warn(`Error in ${info}: "${err.toString()}"`, vm)
  }
  if ((inBrowser || inWeex) && typeof console !== 'undefined') {
    console.error(err)
  } else {
    throw err
  }
}

The article also visualizes the call chain for the created hook using callHook , showing how Vue wraps each lifecycle hook with invokeWithErrorHandling , which then funnels errors to handleError .

3. Error Capture Flow Analysis

For the created phase, the flow is: callHook → invokeWithErrorHandling → handleError → (errorCaptured hooks) → globalHandleError → logError . For click events, Vue registers the handler via updateListeners , which creates an invoker that internally calls invokeWithErrorHandling for each listener, ensuring the same error‑propagation path.

Key points highlighted:

Each component’s lifecycle hooks are wrapped with invokeWithErrorHandling , guaranteeing error capture.

Event listeners are also wrapped, so click‑related errors follow the same pipeline.

The global errorHandler is the final catch‑all, with logError providing developer‑friendly output.

In conclusion, the article emphasizes that Vue’s error handling, while not often discussed in interviews, is straightforward once the source is understood. Mastery of these mechanisms can be a valuable differentiator in technical interviews.

frontendJavaScriptVue.jserror handlingSource CodeVue2
Rare Earth Juejin Tech Community
Written by

Rare Earth Juejin Tech Community

Juejin, a tech community that helps developers grow.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.