javascriptvue.jsvuejs2vue-component

Not able to execute vue's global errorHandler in a few cases


Though I am having issues with a vue 2 project, the demo also faces a similar issue where the global error handler defined in main.js is not working

Vue 3 https://stackblitz.com/edit/vitejs-vite-svaosh?file=src%2Fmain.js

Error Handler

app.config.errorHandler = (err) => {
  console.log('error caught');
};

App.vue

<script>
export default {
  created() {
    console.log('jello');
    throw new Error('dasf');
    this.loadData();
  },

  methods: {
    async loadData() {
      throw new Error('dasf');
    },
  },
};
</script>

I expect both of these errors to be caught by errorHandler and just show a simple console

I assume the errors are in Vue context in not in window context, since vue does show them as unhandled errors like this

enter image description here

Vue2

I was trying to implement an optional error capturing mechanism somehow, where if an api throws an error, I can catch it either in the component if required else the global error handler catches it and shows a warning toast or something.

For some reason it was working fine before, I don't how what is broken but it doesn't work now for me, In my project global error handler catches an error thrown in created but does not catch one if it is thrown in loadData

export default {
  async created() {
    this.loadMastersCount();
    throw new Error("dasf"); // this one is caught by global error handler
  },
  methods: {
    async loadMastersCount() {
      throw new Error("dasf"); // this one is not caught and shown in red during dev on on screen
    },
  }
}

Edit I got the vue 2 reproduction working, here is it

Stackblitz

Github

Case 1 - I throw error in loadData, it is not caught

<script>
import HelloWorld from './components/HelloWorld.vue'

import { failingApi } from "@/api/dummy";

export default {
  name: 'App',
  components: {
    HelloWorld
  },
  async created() {
    // await failingApi();
    this.loadData();
  },
  methods: {
    async loadData() {
      await failingApi();
    }
  }
}
</script>

enter image description here


Case 2 - I throw error in created, it gets caught by global errorHandler

<script>
import HelloWorld from './components/HelloWorld.vue'

import { failingApi } from "@/api/dummy";

export default {
  name: 'App',
  components: {
    HelloWorld
  },
  async created() {
    await failingApi();
    // this.loadData();
  },
  methods: {
    async loadData() {
      await failingApi();
    }
  }
}
</script>

enter image description here

please check @moritz-ringler


Solution

  • In the stackblitz, the error in the created hook is thrown before the handler is registered:

    const app = createApp(App)
    app.mount('#app') // <--- exception is triggered here
    app.config.errorHandler = (err) => {...}
    

    Register the handler before calling app.mount() to fix the issue:

    const app = createApp(App)
    app.config.errorHandler = (err) => {...}
    app.mount('#app')
    

    In the Vue 2 code, it looks like the error in created() isn't actually caught, but never thrown, because execution stops after the uncaught error inloadMastersCount().

    Note that you have to await an async function to catch errors (see this or this answer for explanation)

    Vue.config.errorHandler = (error) => console.log('got global error', error.toString())
    
    const ThrowError = {
      template: `<div>Template</div>`,
      async created() {
        await this.loadData()
      },
      methods: {
        async loadData() {
          await this.throwError()
        },
        async throwError(){
          throw new Error('Error in Promise')
        },
      }
    }
    
    new Vue({
      el: '#app',
      components: {ThrowError},
      template: `<ThrowError/>`,
    })
    <div id="app"></div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.7.16/vue.min.js"></script>