Meituan-Dianping/mpvue · error

Cannot find element: ${el}

Error message

Cannot find element: ${el}

What it means

Vue's query() util resolves the mount target: when el is a string selector it calls document.querySelector. If nothing matches, Vue warns 'Cannot find element: <selector>' and substitutes an empty detached <div>, so the app mounts into a throwaway node instead of the intended element (usually nothing becomes visible).

Source

Thrown at src/platforms/web/util/index.js:16

/* @flow */

import { warn } from 'core/util/index'

export * from './attrs'
export * from './class'
export * from './element'

/**
 * Query an element selector if it's not an element already.
 */
export function query (el: string | Element): Element {
  if (typeof el === 'string') {
    const selected = document.querySelector(el)
    if (!selected) {
      process.env.NODE_ENV !== 'production' && warn(
        'Cannot find element: ' + el
      )
      return document.createElement('div')
    }
    return selected
  } else {
    return el
  }
}

View on GitHub (pinned to 6c5d78ee04)

Solutions

  1. Move the script to the end of <body> or add defer, or wrap mount in DOMContentLoaded so the target exists first.
  2. Verify the selector string matches an existing element id/class exactly (case-sensitive ids).
  3. Mount to document.body or an explicitly created element if the target should be generated.
  4. Check that no other script removes or replaces the target element before mounting.

Example fix

// before
// <head> inline script
new Vue({ el: '#app', render: h => h(App) })
// after
document.addEventListener('DOMContentLoaded', () => {
  new Vue({ el: '#app', render: h => h(App) })
})
Defensive patterns

Strategy: validation

Validate before calling

function requireMountTarget(selector) {
  const el = document.querySelector(selector)
  if (!el) throw new Error('Mount target not found: ' + selector)
  return el
}
// new Vue({ el: requireMountTarget('#app') ... }) — throws before Vue substitutes a dummy div

Type guard

function elementExists(el) {
  return typeof el === 'string' ? document.querySelector(el) !== null : el instanceof Element
}

Try / catch

try {
  new Vue({ el: '#app', render: h => h(App) })
} catch (e) {
  console.error('Mount failed:', e.message)
}

Prevention

When it happens

Trigger: new Vue({ el: '#app' }) (or $mount('#app')) where no element with that selector exists in the DOM at call time — the script ran before the DOM was parsed, the id/class is misspelled, or the element is inside a not-yet-rendered section.

Common situations: Loading a bundle in <head> without defer/DOMContentLoaded; typo in the selector; mounting into an element added later by another script; SPA mounted into a container removed by a prior framework; SSR/hydration mismatches where the element is absent.

Related errors


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