Meituan-Dianping/mpvue · warning

Invalid handler for event

Error message

Invalid handler for event "${event.name}": got ${String(cur)}

What it means

During vnode update, an entry in the `on` listeners object is `undefined`/`null`, meaning the component asked to listen to an event but supplied no handler function. Vue warns and skips attaching the listener.

Solutions

  1. Remove the listener key entirely when there is no handler, instead of setting it to undefined
  2. Guard with a fallback: `on: { click: this.onClick || (() => {}) }`
  3. Filter out falsy handlers before passing: `on: Object.fromEntries(Object.entries(handlers).filter(([, fn]) => fn))`
  4. Fix misspelled handler references

Example fix

// before
h('input', { on: { input: props.onInput } }) // onInput may be undefined
// after
const handlers = {}
if (props.onInput) handlers.input = props.onInput
h('input', { on: handlers })
Defensive patterns

Strategy: type-guard

Validate before calling

function validOn (on) {
  const out = {}
  for (const k in on) if (typeof on[k] === 'function') out[k] = on[k]
  return out
}
// usage: h(Comp, { on: validOn(handlers) })

Type guard

function isHandler (fn) { return typeof fn === 'function' }

Prevention

When it happens

Trigger: `h(MyComp, { on: { click: undefined } })`; spreading an object of handlers where a key exists but its value is undefined; building `on` from reactive data where a handler is conditionally absent.

Common situations: Dynamically assembling listener maps in render functions; destructuring props that lack a handler; TypeScript-less code where a handler name is misspelled and resolves to undefined.

Related errors


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

Appendix: source

Thrown at src/core/vdom/helpers/update-listeners.js:56

  }
  invoker.fns = fns
  return invoker
}

export function updateListeners (
  on: Object,
  oldOn: Object,
  add: Function,
  remove: Function,
  vm: Component
) {
  let name, cur, old, event
  for (name in on) {
    cur = on[name]
    old = oldOn[name]
    event = normalizeEvent(name)
    if (isUndef(cur)) {
      process.env.NODE_ENV !== 'production' && warn(
        `Invalid handler for event "${event.name}": got ` + String(cur),
        vm
      )
    } else if (isUndef(old)) {
      if (isUndef(cur.fns)) {
        cur = on[name] = createFnInvoker(cur)
      }
      add(event.name, cur, event.once, event.capture, event.passive)
    } else if (cur !== old) {
      old.fns = cur
      on[name] = old
    }
  }
  for (name in oldOn) {
    if (isUndef(on[name])) {
      event = normalizeEvent(name)
      remove(event.name, oldOn[name], event.capture)
    }

View on GitHub (pinned to 6c5d78ee04)