Meituan-Dianping/mpvue · error
$listeners is readonly.
Error message
$listeners is readonly.
What it means
Comes from the dev-only setter trap installed on $listeners in initRender. $listeners is the reactive, getter-only object of parent-declared event handlers (v-on bindings) on the component, refreshed by the framework whenever the parent re-renders. Code that does this.$listeners = ... or mutates it triggers this trap; such writes are discarded because the parent vnode's data is the single source of truth for these handlers.
Source
Thrown at src/core/instance/render.js:58
// bind the createElement fn to this instance
// so that we get proper render context inside it.
// args order: tag, data, children, normalizationType, alwaysNormalize
// internal version is used by render functions compiled from templates
vm._c = (a, b, c, d) => createElement(vm, a, b, c, d, false)
// normalization is always applied for the public version, used in
// user-written render functions.
vm.$createElement = (a, b, c, d) => createElement(vm, a, b, c, d, true)
// $attrs & $listeners are exposed for easier HOC creation.
// they need to be reactive so that HOCs using them are always updated
const parentData = parentVnode && parentVnode.data
/* istanbul ignore else */
if (process.env.NODE_ENV !== 'production') {
defineReactive(vm, '$attrs', parentData && parentData.attrs, () => {
!isUpdatingChildComponent && warn(`$attrs is readonly.`, vm)
}, true)
defineReactive(vm, '$listeners', parentData && parentData.on, () => {
!isUpdatingChildComponent && warn(`$listeners is readonly.`, vm)
}, true)
} else {
defineReactive(vm, '$attrs', parentData && parentData.attrs, null, true)
defineReactive(vm, '$listeners', parentData && parentData.on, null, true)
}
}
export function renderMixin (Vue: Class<Component>) {
Vue.prototype.$nextTick = function (fn: Function) {
return nextTick(fn, this)
}
Vue.prototype._render = function (): VNode {
const vm: Component = this
const {
render,
staticRenderFns,
_parentVnodeView on GitHub (pinned to 6c5d78ee04)
Solutions
- Do not assign to this.$listeners; read it (e.g. v-on="$listeners" for HOC pass-through) only
- To add your own handlers, declare them with $emit/$on or merge them at template level: v-on="{ ...$listeners, click: handleClick }"
- To modify behavior, wrap listeners in computed properties instead of mutating the object
Defensive patterns
Strategy: fallback
When it happens
Trigger: Thrown at src/core/instance/render.js:58 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of Meituan-Dianping/mpvue@6c5d78ee04 (2026-09-02).
Data as JSON: /api/errors/f90aa762325f8152.
Report an issue: GitHub.