Meituan-Dianping/mpvue · warning

Avoid deleting properties on a Vue instance or its root $dat

Error message

Avoid deleting properties on a Vue instance or its root $data - just set it to null.

What it means

Warning from Vue.delete / vm.$delete (del in observer/index.js) when the target is a Vue instance or the root $data object. Deleting keys from these breaks the reactive dependency graph, so Vue warns and instead recommends setting the property to null.

Source

Thrown at src/core/observer/index.js:268

  if (!target.__keyPath) {
    def(target, '__keyPath', {}, false)
  }
  target.__keyPath[key] = true
  ob.dep.notify()
  return val
}

/**
 * Delete a property and trigger change if necessary.
 */
export function del (target: Array<any> | Object, key: any) {
  if (Array.isArray(target) && isValidArrayIndex(key)) {
    target.splice(key, 1)
    return
  }
  const ob = (target: any).__ob__
  if (target._isVue || (ob && ob.vmCount)) {
    process.env.NODE_ENV !== 'production' && warn(
      'Avoid deleting properties on a Vue instance or its root $data ' +
      '- just set it to null.'
    )
    return
  }
  if (!hasOwn(target, key)) {
    return
  }
  delete target[key]
  if (!ob) {
    return
  }
  if (!target.__keyPath) {
    def(target, '__keyPath', {}, false)
  }
  // Vue.del 删除对象属性,渲染时候把这个属性设置为 undefined
  target.__keyPath[key] = 'del'
  ob.dep.notify()

View on GitHub (pinned to 6c5d78ee04)

Solutions

  1. Replace the delete with an assignment to null (or undefined semantics via null)
  2. Nest such keys one level down in a data sub-object so Vue.delete works reactively
  3. Declare the key permanently in data and toggle its value instead of removing it
  4. If the item belongs to a list, remove it from the array with splice or $delete on the array index

Example fix

// before
this.$delete(this.$data, 'draft')
// after
data() { return { draft: null } }
methods: { clearDraft() { this.draft = null } }
Defensive patterns

Strategy: validation

Validate before calling

function isSafeDeleteTarget(target) {
  return target != null && typeof target === 'object' && !target._isVue && !(target.__ob__ && target.__ob__.vmCount)
}

Type guard

function isRootReactive(t) { return t != null && (t._isVue === true || (t.__ob__ && t.__ob__.vmCount > 0)) }

Prevention

When it happens

Trigger: Vue.delete(vm, 'someKey'); Vue.delete(this.$data, 'someKey'); this.$delete(this.$data, key) in cleanup logic; using the delete operator on root data keys via a wrapper.

Common situations: Cleanup after removing form fields or list items stored at root; state-reset utilities that prune keys; code translated from plain-object state management where delete was routine.

Related errors


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