Subscribe on changes!

Add line number and a snippet of the source template to template render error reports

avatar
May 4th 2022

What problem does this feature solve?

This is replicating here feature issue https://github.com/vuejs/vue/issues/10966 from the Vue 2 repo. I'm willing to work on this as a PR for Vue 3 but would like to ensure the maintainers are receptive to this feature and get any additional information and background info that might be relevant.

This feature helps developers pinpoint template errors in larger templates.

At the moment, render errors look like this (from version 2.5.18 but confirmed to still be along these lines in latest Vue 3 release):

vue.js:616 [Vue warn]: Error in render: "TypeError: Cannot read property 'name' of undefined"

found in

---> <ASelectDate>
       <ALite>
         <TransitionGroup>
           <DbNavigation>
             <VContent>
               <VApp>
                 <Root>
warn @ vue.js:616
[...]
fn._withTask.fn._withTask @ vue.js:1913

vue.js:1828 TypeError: Cannot read property 'name' of undefined
    at Proxy.eval (eval at createFunction (vue.js:10785), <anonymous>:2:39)
    at VueComponent.Vue._render (vue.js:4635)
    at VueComponent.updateComponent (vue.js:2893)
    at Watcher.get (vue.js:3261)
    at new Watcher (vue.js:3250)
    at mountComponent (vue.js:2900)
    at VueComponent.Vue.$mount (vue.js:8642)
    at VueComponent.Vue.$mount (vue.js:11045)
    at init (vue.js:4225)
    at createComponent (vue.js:5696)

While TypeError: Cannot read property 'name' of undefined and the template it occurred in is of course quite useful information it could be better if there are many references to 'name' in <ASelectDate> and the exact location of the error is not obvious. I'm proposing a feature enhancement that would include a line number relative to the template itself (assuming it is not just a render function) and also output the line before, the line of the error and the line following it from the source template to provide context information to the developer.

I believe this can be achieved using the same techniques that are used in compilers when debugging information is enabled and generated. In development mode, as a template is compiled, context information is maintained (line numbers and the source lines of the template) and as each piece is compiled and converted into render function code this information is captured as "debugging symbols" (using compiler terms). If this debugging information is available when a render error occurs, the stack trace is examined and used with the debugging information to determine the line number and template lines to display with the warning.

The result would be an error report that looks something like:

vue.js:616 [Vue warn]: Error in render: "TypeError: Cannot read property 'name' of undefined"

found in

---> <ASelectDate>
       <ALite>
         <TransitionGroup>
           <DbNavigation>
             <VContent>
               <VApp>
                 <Root>

on line 34

        <p class="model-year">{{ model.year }}</p>
--->    <p class="model-name">{{ model.name }}</p>
        <p class="model-tagline">{{ model.tag_line }}</p>

What does the proposed API look like?

In terms of implementation details, this feature would be enabled in development mode. The debugging information would be generated during template compilation and could be attached to the render function itself when compiled and emitted so that no additional files need to be produced, packaged or loaded. If the debugging information is available, the error message as envisioned above is produced. If not, the current style of warning is emitted instead along with a message that says for better details, reproduce the error in development mode.