Package: @appsignal/vue 1.1.7
Vue version: 3.5.x
The errorHandler in @appsignal/vue has two problems when used with Vue 3:
1. Crash when Vue invokes the handler with a null instance
Vue 3 calls app.config.errorHandler(err, instance, info) with instance: null for errors outside a component context (e.g. errors in watchers or lifecycle hooks after unmount). The handler dereferences the instance unguarded:
const componentName = vm.$vnode
? vm.$vnode.componentOptions.tag // Vue 2
: vm.$options.name || vm.$options.__name // Vue 3
With vm = null this throws TypeError: Cannot read properties of null (reading '$vnode') inside the error handler itself, so the original error is never reported to AppSignal and never reaches console.error.
2. Component name resolution effectively never works on Vue 3
- The
vm.$vnode branch is Vue 2 API; on Vue 3 it is always undefined, so it is dead code.
$options.name is only set for components that declare an explicit name option, which most codebases don't do (the SFC filename is usually the source of truth).
$options.__name is only set for <script setup> components.
For classic Options API SFCs without an explicit name, none of the branches match, so every error is reported with the action [unknown Vue component]. In practice this means all frontend errors group under a single incident, which defeats per-component grouping.
Suggested fix
function componentName(vm) {
const options = vm?.$options
if (!options) return null
const file = options.__file?.split("/").pop()?.replace(/\.vue$/, "")
return options.name || options.__name || file || null
}
- Optional chaining fixes the null-instance crash.
$options.__file is set by vue-loader (always in development; in production when the app opts in via vue-loader's exposeFilename option, which reduces it to the basename). It is a safe extra fallback: absent unless the app opted in, and the [unknown Vue component] fallback is preserved otherwise.
I've opened a PR with this change plus tests alongside this issue.
Package:
@appsignal/vue1.1.7Vue version: 3.5.x
The
errorHandlerin@appsignal/vuehas two problems when used with Vue 3:1. Crash when Vue invokes the handler with a null instance
Vue 3 calls
app.config.errorHandler(err, instance, info)withinstance: nullfor errors outside a component context (e.g. errors in watchers or lifecycle hooks after unmount). The handler dereferences the instance unguarded:With
vm = nullthis throwsTypeError: Cannot read properties of null (reading '$vnode')inside the error handler itself, so the original error is never reported to AppSignal and never reachesconsole.error.2. Component name resolution effectively never works on Vue 3
vm.$vnodebranch is Vue 2 API; on Vue 3 it is alwaysundefined, so it is dead code.$options.nameis only set for components that declare an explicitnameoption, which most codebases don't do (the SFC filename is usually the source of truth).$options.__nameis only set for<script setup>components.For classic Options API SFCs without an explicit
name, none of the branches match, so every error is reported with the action[unknown Vue component]. In practice this means all frontend errors group under a single incident, which defeats per-component grouping.Suggested fix
$options.__fileis set by vue-loader (always in development; in production when the app opts in via vue-loader'sexposeFilenameoption, which reduces it to the basename). It is a safe extra fallback: absent unless the app opted in, and the[unknown Vue component]fallback is preserved otherwise.I've opened a PR with this change plus tests alongside this issue.