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

  1. Remove any assignment to this.$attrs; treat it as read-only
  2. 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
  3. 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.