Meituan-Dianping/mpvue · warning

Template element not found or is empty: ${options.template}

Error message

Template element not found or is empty: ${options.template}

What it means

When the `template` option is a string starting with '#', Vue treats it as a CSS selector/id and fetches the element's innerHTML as the template. If no element matches (or it is empty), a dev-mode warning is emitted and compilation proceeds without a usable template.

Source

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

  /* istanbul ignore if */
  if (el === document.body || el === document.documentElement) {
    process.env.NODE_ENV !== 'production' && warn(
      `Do not mount Vue to <html> or <body> - mount to normal elements instead.`
    )
    return this
  }

  const options = this.$options
  // resolve template/el and convert to render function
  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 */

View on GitHub (pinned to 6c5d78ee04)

Solutions

  1. Verify an element with that id exists and is non-empty BEFORE creating the Vue instance.
  2. Define the template inline as a string instead of referencing an id.
  3. Ensure the <script type="text/x-template" id="..."> loads before your JS runs (script order / DOMContentLoaded).

Example fix

// before
template: '#tpl-user' // element missing
// after
template: '<div class="user">{{ name }}</div>'
// or ensure: <script type="text/x-template" id="tpl-user">...</script> exists before init
Defensive patterns

Strategy: validation

Validate before calling

function assertTemplateElementExists (selector) {
  const el = document.querySelector(selector)
  if (!el || !el.innerHTML.trim()) {
    throw new Error('Template element not found or is empty: ' + selector)
  }
}
assertTemplateElementExists('#tpl-user')

Type guard

const templateExists = (sel) => {
  const el = typeof sel === 'string' && sel.charAt(0) === '#' ? document.querySelector(sel) : null
  return !!el && el.innerHTML.trim().length > 0
};

Prevention

When it happens

Trigger: new Vue({ template: '#my-template' }) or component template '#id' where the id selector matches nothing (element removed, script placed after app init, typo in id, or empty element).

Common situations: x-template script blocks deleted or moved by bundlers; templates defined after Vue instantiation; SPA route renders clearing the DOM before mount; id typos.

Related errors


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