Meituan-Dianping/mpvue · warning
$props is readonly.
Error message
$props is readonly.
What it means
Vue exposes the component's props as a read-only `$props` object on the instance. In development builds, a setter is defined on `$props` that fires this warning if any code attempts to assign to it. Props are owned by the parent component, so mutating them from the child would break one-way data flow.
Source
Thrown at packages/weex-vue-framework/factory.js:3315
function stateMixin (Vue) {
// flow somehow has problems with directly declared definition object
// when using Object.defineProperty, so we have to procedurally build up
// the object here.
var dataDef = {};
dataDef.get = function () { return this._data };
var propsDef = {};
propsDef.get = function () { return this._props };
if (process.env.NODE_ENV !== 'production') {
dataDef.set = function (newData) {
warn(
'Avoid replacing instance root $data. ' +
'Use nested data properties instead.',
this
);
};
propsDef.set = function () {
warn("$props is readonly.", this);
};
}
Object.defineProperty(Vue.prototype, '$data', dataDef);
Object.defineProperty(Vue.prototype, '$props', propsDef);
Vue.prototype.$set = set;
Vue.prototype.$delete = del;
Vue.prototype.$watch = function (
expOrFn,
cb,
options
) {
var vm = this;
if (isPlainObject(cb)) {
return createWatcher(vm, expOrFn, cb, options)
}
options = options || {};View on GitHub (pinned to 6c5d78ee04)
Solutions
- Remove the assignment to `this.$props`; treat it as strictly read-only.
- If you need local editable state seeded from props, copy into `data` (e.g. `data() { return { local: this.someProp } }`).
- To change a prop's value, emit an event to the parent (`this.$emit('update:x', v)`) or use `v-model`/`.sync` so the parent updates it.
Example fix
// before
this.$props = { ...this.$props, title: 'new' };
// after
this.$emit('update:title', 'new'); Defensive patterns
Strategy: validation
Validate before calling
if (import.meta.env.MODE !== 'production' && myCodeAssignsToProps) {
throw new Error('Never assign to this.$props; emit an event instead');
} Type guard
function isReadOnlyPropsRef(target) {
return target && target.$props !== undefined && Object.getOwnPropertyDescriptor(Vue.prototype, '$props').set !== undefined;
} Prevention
- Treat $props as immutable; lint with eslint-plugin-vue's no-mutating-props rule.
- Copy props into data for local editing.
- Communicate changes upward with $emit.
When it happens
Trigger: Any assignment like `this.$props = {...}`, `vm.$props.foo = x` triggering the setter (only the wholesale assignment triggers the setter), or destructuring-and-reassigning `$props` inside a component method, lifecycle hook, or mixin.
Common situations: Developers trying to 'reset' props after a parent update, old Vue 1.x code migrated to Vue 2 that mutated props directly, or generated/compiled render code accidentally writing to `$props`.
Related errors
- Avoid mutating a prop directly since the value will be overw
- Avoid mutating an injected value directly since the changes
- Avoid using observed data object as vnode data: ${JSON.strin
- The computed property "${key}" is already defined as a prop.
- $props is readonly.
AI-assisted analysis of Meituan-Dianping/mpvue@6c5d78ee04 (2026-09-02).
Data as JSON: /api/errors/23bb705bce1403d1.
Report an issue: GitHub.