Meituan-Dianping/mpvue · error
$attrs is readonly.
Error message
$attrs is readonly.
What it means
Comes from the dev-only setter trap placed on the $attrs property during initRender. $attrs (the container element attributes passed down to a component) is defined with a getter only and is meant to be read — primarily for higher-order-component pass-through via v-bind="$attrs". Assigning to it (this.$attrs = ...) hits this trap; the framework manages $attrs internally from the parent vnode's data on every parent re-render, so user writes to it are rejected.
Source
Thrown at src/core/instance/render.js:55
const renderContext = parentVnode && parentVnode.context
vm.$slots = resolveSlots(vm.$options._renderChildren, renderContext)
vm.$scopedSlots = emptyObject
// 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 {View on GitHub (pinned to 6c5d78ee04)
Solutions
- Remove any assignment to this.$attrs; treat it as read-only
- To alter attributes on the root element, set normal attributes on the component's root node or use attrs in the component's own template
- If you need a mutable copy, clone it into data: data() { return { attrs: { ...this.$attrs } } }
Defensive patterns
Strategy: fallback
When it happens
Trigger: Thrown at src/core/instance/render.js:55 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/c9b1555017590385.
Report an issue: GitHub.