Guide to Error & Exception Handling in Vue Apps

We all try to debug and test our apps the best we can, but we can’t really prevent errors and exceptions from happening. Sometimes, something as simple as a HTTP request will fail – just because. But as always in life, what matters is how you handle problems that inevitably pop up 🧘‍♂️

Here’s an introduction to error and exception handling in your Vue apps.

What is the difference between debugging, testing and exception handling?

The concepts of debugging, testing and error handling are often used together. If you’re starting out, the differences between them may not be clear enough. So we’ll start with defining them:

  • 🧪 Testing is the process of making sure that your app is working as intended. It helps you identify problems and bugs in your code during development or before deploying. It’s usually automated to a degree, but human QA will test your apps in a more user-centric, exploratory way to find different issues. (Read our guide to testing Vue apps)
  • 🐛 Debugging describes the process of resolving issues that you already know about (for example through testing and tracing the error back to its origin). By investigating what went wrong and fixing it, you’re debugging. (Read our guide to debugging Vue apps)
  • 💥 Exception handling makes sure that your app deals with any errors that may happen without crashing. In case an error occurs, we can define how our app will react and recover from it.

All of these things work together to develop reliable and stable apps. Today, we’re going to take a closer look at exception handling!

Why we need to handle errors & exceptions

Are you still a bit unsure why exactly error handling is important, or why we might want to put more thought into it than just showing a generic error page?

In dev terms we want our app to fail gracefully, which just means in a controlled way. If you remember getting frustrated at an error message that just said „An unexpected error occurred“, or an app that crashed on you, you have experienced a not-so-graceful failing.

Handling specific errors and trying to solve them for your user is a great way to improve user experience. Failed to fetch new data? Try again, or offer the user the option to retry. Couldn’t save settings because of a network error? Tell the user so they can troubleshoot their connection.

Handling and logging errors correctly also improves your experience as a developer, because it usually makes it a lot easier to debug, and prevents losing data.

Vue error handling techniques you should know

There are a few different options how to handle errors in your app and components. Depending on your project, you might use different techniques.

We’re introducing them going from a broad scope (handling errors globally for your whole app) to more specific (handling errors in components or distinct operations).

Global error handling

Your first step will probably always be to add global error handling with the Vue errorHandler.

Add this function to your main application file (usually main.js / main.ts), so it gets called whenever an error happens in a component, hook, watcher, event handlers etc. of your Vue app. This makes sure our app doesn’t crash, and gives us options to handle those exceptions instead.

You can add your custom logic to it, but at least we should log the error and display an error message.

import { createApp } from 'vue';

const app = createApp({});

// Global error handler
app.config.errorHandler = (err, instance, info) => {

  // Handle the error globally
  console.err("Global error:", error);
  console.log("Vue instance:", instance);
  console.log("Error info:", info);

  // Add code for UI notifications, reporting or other error handling logic
};

app.mount("#app")’

The global error handler receives the JS error object, the Vue instance where the error happens and additional Vue-specific info about the error to help you pinpoint the problem.

Component error handling

To get more specific, we can use the errorCaptured (options API) option or onErrorCaptured() (composition API) lifecycle hook that gets called when an error occurs within a component’s scope or its child components. This includes errors during component rendering or computed properties.

Catching errors at this level gives you more control over the error handling of specific scenarios. You can for example use a component-specific UI for fallbacks and error messages. It also lets you implement specific error tracking to better analyze problems with that component.

<template>
  <div>
    <button @click="throwError">Throw Error</button>
    <p>{{ message }}</p>
  </div>
</template>

<script setup>
import { ref, onErrorCaptured } from 'vue';

const message = ref('');

const throwError = () => {
  throw new Error('Simulated error');
};

onErrorCaptured((err) => {
  message.value = 'An error occurred: ' + err.message;
  return false;
});
</script>

Preventing the error from bubbling up with return false will make sure that your global error handling does not react to the error, which it would due to error propagation rules.

Error handling for routing

To specifically handle routing errors, we can use the router.onError method by Vue Router.

// Handle router errors
router.onError((err) => {
  // Handle the router error here
  console.error("Router error:", err);
  // Add code for reporting or other error handling logic
});

Try...Catch blocks

If a part of your app contains potentially error-prone code, you can wrap it in a try/catch block to handle any problems immediately. Synchronous operations like API calls are great candidates for that!

fetchData() {
   try {
   // Add functions that may fail here
   // If an error occurs, it will be caught:
      } catch (err) {
        // Handle the error here
        console.error("Error:", err);
      }
    }

Tools for your Vue error handling workflow

Now that you have everything you need to get started with Vue error handling, we’re going to end this guide with some resources that will improve your dev experience.

Vue Dev Tools

The Vue DevTools extension is mainly a tool to enhance your debugging experience, which is of course connected to your error handling logic. It’s an indispensable extension for every Vue dev.

Vue Devtools Debugging Tools for Vue Apps
icon-eye-dark Created with Sketch. 9.869

Here are the feature highlights for error handling:

  • Log: Most importantly, this is where your error messages and information will show up, if you log them within your error handling logic. Inspecting them, you will get a detailed error stack trace including line numbers & functions.
  • Error highlighting: A component that throws an error will be marked in the component tree so it’s easier for you to identify where things went wrong

Error Monitoring Tools

Logs are nice and all, but if you want to stay on top of all the errors that your users might be experiencing, a monitoring service will help you a lot. It also makes the experience of debugging less frustrating.

Error monitoring tools can notify you if your users experience issues, and provide a dashboard UI to learn more information about the problem. They show you which users are impacted, and display stack traces & breadcrumbs of events.

We’re running a SaaS product and have set up such a monitoring workflow for it. It brings us peace of mind and helps us make sure our users have a good experience. We already mentioned that we personally use Sentry for error and performance monitoring – here's a walkthrough of a debugging session where we use it. Disclaimer: They are also sponsoring MadeWithVueJS, but we have been using their service forever and would recommend it regardless 💚

Sentry for Vue Vue Error & Performance Monitoring
icon-eye-dark Created with Sketch. 22.383

There are of course many more tools to choose from, but they all more less work the same: They capture any errors, uncaught exceptions and other types of problems across your stack automatically once you add and configured their SDKs. Sentry reports errors from our Vue frontend and Laravel backend, for example.

You can also capture errors manually by passing your error objects and adding metadata like context, users, transaction names, release versions, attachments or tags. Here’s how that would look like for Sentry, so you get the idea:

import * as Sentry from "@sentry/vue";

try {
    // Add functions that may fail here
} catch (err) {
    Sentry.setUser({ email: "john.doe@example.com" });
    Sentry.setTag("page_locale", "de-at");
    Sentry.captureException(err);

    // Handle the error here
}

There’s an open Vue School course about Application Monitoring in Vue.js with Sentry that you can watch to learn more.

Conclusion

We’ve now explored some different error handling strategies and learned about how exception handling ties together with debugging and testing to create sturdy Vue apps.

Now go forth and build some quality experiences with your (and our) favorite framework!

Similar Articles
Build a Progressive Web App In VueJs, from Zero to Hero! [via Hackernoon]
15.01.2019  •  in #Tutorial, #Bookmarks
In case you didn't notice: Everyone is doing Progressive Web Apps now! Read this article series by Fabian Hinsenkamp to create your own PWA with Vue.js!
Best Vue Form Libraries of 2024
26.03.2024  •  in #UI Components
Forms are an important ingredient for almost every web app. But they can get complex pretty fast, and you’ll have to work through the repetitive processes of handling, storing and validating your data for every custom form. At some point, you'll be...