[Vue warn]: $attrs is readonly


I get warnings on keypresses, they are:

[Vue warn]: $attrs is readonly.
[Vue warn]: $listeners is readonly.
[Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "focus"

All of the warnings stem from the same component,

found in

---> <StepInput> at src/StepInput.vue

But I do not use $attrs or $listeners explicit anywhere. I’m pretty sure I do not mutate focus also, and I’m stuck trying to figure out what’s going on.

I’ve tried to simplify for an example, but are not able to replicate it in the simpler example. Therefor I’m pasting the whole component here:


    @input="$emit('input', $event.target.value)"
    @keydown.tab.prevent="$emit('focus', i + 1)"
    @keydown.down.prevent="$emit('focus', i + 1)"
    @keydown.shift.tab.prevent="$emit('focus', i - 1)"
    @keydown.up.tab.prevent="$emit('focus', i - 1)"
    @click="$emit('focus', i)">
export default {
  props: ['value', 'i', 'last', 'focus'],
  data: function () {
    return {
      input: this.value,
      empty: false
  directives: {
    focus: function (el, binding) {
      // <element v-focus="true"> will focus element
      if (binding.value) {
  methods: {
    addStep: function (event) {
      if (event.target.selectionStart === 0) {
        // enter and marker in beginning of input field
        // -> insert new input and shift rest of steps down
        this.$emit('add', this.i)
      } else if (this.last) {
        // add step at bottom, increment focus
        this.$emit('add', this.i + 1)
        this.$emit('focus', this.i + 1)
      } else {
        // enter on input in the middle
        this.$emit('focus', this.i + 1)
    removeStep: function (event) {
      if (!this.empty && this.input === '') {
        this.empty = true;
      } else if (this.empty) {
        this.$emit('remove', this.i)
        if (event.keyCode !== 46 || this.last) {
          // backspace key or in end
          // delete key keeps focus on same input
          this.$emit('focus', this.i - 1)

I use Vue 2.4.4 and poi 9.3.5 for bundling. The bundling is in “development” mode.

Any thoughts?


Yes, and I use the component like this…

      <div class="step" v-for="(step, i) in steps" :key="step.i">
          :focus="focus === i && !saveModal"
          :last="step.i === (steps.length - 1)"
        <div class="output">Output <span>{{ outputs[step.i] }}</span></div>


What does the v-focus directive do? I assume it mutates the prop…


Edit, sorry. It’s above, but I’ll paste here. I cannot see that the value is mutated…

  directives: {
    focus: function (el, binding) {
      // <element v-focus="true"> will focus element
      if (binding.value) {


Oh, right - sorry. Hm, no idea right now :frowning:


The warnings do not appear when putting the main component (where the state lives) in a .vue file and mounting it like this:

import Vue from 'vue/dist/vue.esm.js'
import App from './App.vue'

new Vue({
  el: '#container',
  components: {
    app: App


I can also add that the warnings also disappears when removing @focus="setFocus" in the template. So it’s setFocus that triggers the warnings.


Hi. I came upon a similar issue, and eventually figured it out.

Following the call stack, I found I was using two different vue bundles (vue.esm.js) in code.

More precisely, the updateChildComponent function in src/core/instance/lifecycle.js sets the isUpdatingChildComponent flag to true on start and reverts to false on end. The reactive setter function checks the flag:

!isUpdatingChildComponent && warn("$attrs is readonly.", vm, isUpdatingChildComponent);

so updating child vm’s $attrs and $listeners inside should not complain during the process.

I found out the flag was actually set to false, which turned out to be from another vue.esm.js bundle. This happened because I was doing a npm link for an in-house developed component located somewhere else, and the build got mixed up – I got tired of importing from the dist build and imported directly from source. I was actually opening two different vue.esm.js?abcd sourcemapped tabs in Chrome dev tools!

Your case may vary, but seeing the $attrs and $listeners warning together seems highly likely that it’s coming from the same source (updateChildComponent function).

I haven’t heard about poi, but I suggest you check your bundle process anyhow.


@jangxyz Thanks for your explanation. Sounds reasonable, as POI probably bundles .vue-files with the ES-module, and I’ve used the commonjs-module.

I’ll mark this as solved.


My app $attrs an $listener warnings too andI was also removing the files from / dist with ftp because I found it very tedious. I have also made npm run dev at the same time as npm install. My system is corrupt ?. What can I do as it continues to issue errors and warning ?. I hope to have explained myself well since my English is very bad and I do it by google traslator. Thank you.


@jangxyz Thanks! I have a library that i linked in since i’m working on it as well and was getting this issue. Seeing your answer helped me debug that the library was using a different vue file.


Thanks for the post. I had the same issue as I am also doing a npm link for an in-house component library. So do we just have to live with it? Or anything we can do on the in-house library side to get rid of the warning?


i’m getting this error, on button click event.Unable to fix it, I’m getting error from vue.js file


I’m new to vue.js, I dont know why im getting $attrs is readonly, $listner is readonly.how I can fix it?


mostly, click events not working ? how to fix it?


Please open a new topic, and in this topic, please provide more information.

No one will be able to help you with our problem as long as they know nothing about your app.