Meituan-Dianping/mpvue · warning

invalid template option:${template}

Error message

invalid template option:${template}

What it means

Vue's $mount with the runtime-with-compiler build resolves the `template` option by trying selector string, innerHTML string, or DOM node. If the template option is set to something none of these branches can handle (e.g. a number, function, boolean, or null when el is also absent), the compiler cannot proceed and warns 'invalid template option'. The library throws it because a template it cannot interpret means it cannot produce a render function.

Source

Thrown at src/platforms/web/entry-runtime-with-compiler.js:52

  if (!options.render) {
    let template = options.template
    if (template) {
      if (typeof template === 'string') {
        if (template.charAt(0) === '#') {
          template = idToTemplate(template)
          /* istanbul ignore if */
          if (process.env.NODE_ENV !== 'production' && !template) {
            warn(
              `Template element not found or is empty: ${options.template}`,
              this
            )
          }
        }
      } else if (template.nodeType) {
        template = template.innerHTML
      } else {
        if (process.env.NODE_ENV !== 'production') {
          warn('invalid template option:' + template, this)
        }
        return this
      }
    } else if (el) {
      template = getOuterHTML(el)
    }
    if (template) {
      /* istanbul ignore if */
      if (process.env.NODE_ENV !== 'production' && config.performance && mark) {
        mark('compile')
      }

      const { render, staticRenderFns } = compileToFunctions(template, {
        shouldDecodeNewlines,
        delimiters: options.delimiters,
        comments: options.comments
      }, this)
      options.render = render

View on GitHub (pinned to 6c5d78ee04)

Solutions

  1. Ensure `template` is either a string (selector starting with '#', or an HTML string) or a DOM element (has nodeType).
  2. If you meant to render a component, register it via `components` and use it in the template, not as the template value.
  3. If the template comes from a variable, check it is defined and is a string before mounting.
  4. If you don't need a template, remove the option and use `render: h => h(...)` instead (runtime-only builds don't compile templates anyway).

Example fix

// before
new Vue({ template: myComponent, el: '#app' })
// after
new Vue({
  el: '#app',
  components: { myComponent },
  template: '<my-component/>'
})
Defensive patterns

Strategy: validation

Validate before calling

const opts = { template: myTemplate }
const isValidTemplate = t => typeof t === 'string' || (t && typeof t.nodeType === 'number')
if (!isValidTemplate(opts.template)) {
  throw new TypeError('template option must be a selector/HTML string or a DOM node, got: ' + typeof opts.template)
}

Type guard

function isValidTemplate(t) {
  return typeof t === 'string' || (t != null && typeof t.nodeType === 'number')
}

Prevention

When it happens

Trigger: Calling `new Vue({ template: <non-string, non-node> })` then `$mount()`, e.g. `template: 123`, `template: someComponent`, `template: null`, or passing a compiled render template object instead of a string/DOM element.

Common situations: Passing a Vue component object as `template` instead of putting it in `components`; typos like `template: this.someTemplate` where the value is undefined at mount time; using the runtime-only build where the compiler entry path differs; migrating from templates to render functions and leaving a stale template value.

Related errors


AI-assisted analysis of Meituan-Dianping/mpvue@6c5d78ee04 (2026-09-02). Data as JSON: /api/errors/7e264b6449b756b0. Report an issue: GitHub.