Empty error message in production environment when using ESM build
kleinfreund opened this issue · 4 comments
Reproduction
https://github.com/kleinfreund/vue-router-empty-error-reproduction
Steps to reproduce the bug
Steps to reproduce
-
Start the development environment by running
vite
(e.g.npx vite
,yarn vite
). -
Go to http://localhost:5173/ and take note of the console warning and error.
[Vue warn]: Unhandled error during execution of setup function at <RouterLink to= {name: 'non-existing-route'} > at <App>
vue-router.js?v=271f20ea:750 Uncaught Error: No match for {"name":"non-existing-route","params":{}} at createRouterError (vue-router.js?v=271f20ea:750:19) at Object.resolve (vue-router.js?v=271f20ea:1202:15) at Object.resolve (vue-router.js?v=271f20ea:2320:34) at vue-router.js?v=271f20ea:1597:39 at ReactiveEffect.fn (chunk-3CCIBI4V.js?v=271f20ea:1237:13) at ReactiveEffect.run (chunk-3CCIBI4V.js?v=271f20ea:430:19) at get value (chunk-3CCIBI4V.js?v=271f20ea:1249:107) at useLink (vue-router.js?v=271f20ea:1633:22) at setup (vue-router.js?v=271f20ea:1674:27) at callWithErrorHandling (chunk-3CCIBI4V.js?v=271f20ea:1657:19)
-
Build for production by running
vite build
(e.g.npx vite build
,yarn vite build
). -
Run
http-server dist
(e.g.npx http-server dist
,yarn http-server dist
). -
Go to http://localhost:8080/ and take note of the console error.
index-w07yFLF8.js:13 Error at yt (index-w07yFLF8.js:21:6095) at Object.d [as resolve] (index-w07yFLF8.js:21:10933) at Object.T [as resolve] (index-w07yFLF8.js:21:18123) at index-w07yFLF8.js:21:14301 at Zn.fn (index-w07yFLF8.js:9:8939) at Zn.run (index-w07yFLF8.js:9:1446) at get value (index-w07yFLF8.js:9:9183) at index-w07yFLF8.js:21:14349 at Zn.fn (index-w07yFLF8.js:9:8939) at Zn.run (index-w07yFLF8.js:9:1446)
Expected behavior
The error in the production build tells me something about the nature of the route resolution error.
Actual behavior
The error in the production build only has an intact stack trace, but no error message and, importantly, no information about which route couldn’t be resolved including the used parameters is provided.
Additional information
In error monitoring, every now and then, I notice errors that are reported with only a stack trace and no error message whatsoever. The only clue was that, with sourcemaps, the stack trace was related to the following lines of code in vue-router’s ESM build:
else {
return assign(new Error(), {
type,
[NavigationFailureSymbol]: true,
}, params);
}
Corresponding source code:
router/packages/router/src/errors.ts
Lines 138 to 147 in 13303bd
This makes it unnecessarily hard to figure out what’s wrong as all I have to go by when looking at Datadog logs (for example) is a "Error: Empty message" entry and the URL at which it occurred. With a sufficiently complex application, that makes it quite tedious to identify which route resolution is going wrong.
The error still contains all the information. Just not the text message, just its code (type)
Vue core has a similar feature.
The text they print when logged is a different story but the platform you use should be able to give you access to the error object. Other than that, anything missing in the error?
The Error
object that is being logged does indeed hold the relevant information. I can confirm this by adding a custom error handler and logging the object itself:
app.config.errorHandler = function (err, vm, info) {
console.log(err) // has `.location`
}
However, without custom error handling exposing this (we don’t customize errorHandler
in our application), that information is invisible when looking directly at the browser console.
Whether Datadog or other tools at least in theory have the ability to look at the Error
object itself, I don’t know. At least in our setup, any further information beyond the stack trace seems lost.
I see. Then things are working correctly. If you want the error to be logged in a particular way, that’s application code you should add to fit your needs
As a workaround, I’m considering to apply the following custom error handler in our application:
app.config.errorHandler = function (error) {
// Patches the vue-router MATCHER_NOT_FOUND error message back into the error object because vue-router explicitly creates an `Error` object with no message in production environments.
if (
import.meta.env.PROD &&
error instanceof Error &&
error.message === '' &&
'type' in error &&
error.type === 1 &&
'location' in error
) {
// Changing `error.message` causes Vue to throw the error twice even when `errorHandler` throws the same `Error` object.
error.message = `No match for ${JSON.stringify(error.location)}${router.currentRoute.value
? ` while being at ${JSON.stringify(router.currentRoute.value.fullPath)}`
: ''}`
throw error
}
throw error
}