oxc-project/oxc · warning · OxcDiagnostic
`model` definition is deprecated.
Error message
`model` definition is deprecated.
What it means
Diagnostic from oxlint's vue/no-deprecated-model-definition rule (since oxlint 1.63.0). It fires on the Vue 2 `model` option used to customize v-model (e.g. model: { prop: 'checked', event: 'change' }). Vue 3 replaced it with the standard modelValue prop and update:modelValue event, and ignores the old option — the binding silently stops working. The rule's allowVue3Compat option (allow_vue3_compat) permits the exact forwards-compatible shape and routes anything else to this base diagnostic.
Source
Thrown at crates/oxc_linter/src/rules/vue/no_deprecated_model_definition.rs:21
use serde::{Deserialize, Serialize};
use oxc_ast::{
AstKind,
ast::{Expression, ObjectExpression, ObjectPropertyKind},
};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::Span;
use crate::{
AstNode,
context::LintContext,
rule::{DefaultRuleConfig, Rule},
utils::is_vue_component_options_object,
};
fn deprecated_model_diagnostic(span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("`model` definition is deprecated.").with_label(span)
}
fn vue3_compat_diagnostic(span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn(
"`model` definition is deprecated. You may use the Vue 3-compatible `modelValue`/`update:modelValue` though.",
)
.with_label(span)
}
#[derive(Debug, Default, Clone, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase", default, deny_unknown_fields)]
struct NoDeprecatedModelDefinitionConfig {
/// Allow `model: { prop: 'modelValue', event: 'update:modelValue' }` (or
/// the kebab-case `model-value` variant) which is forwards-compatible with
/// Vue 3's `v-model`.
allow_vue3_compat: bool,
}
View on GitHub (pinned to e1e7af627c)
Solutions
- Rename the prop to modelValue and emit update:modelValue: this.$emit('update:modelValue', val)
- If the component already targets the compat shape, verify prop: 'modelValue', event: 'update:modelValue' exactly and set allowVue3Compat: true
- For named v-models (v-model:title), use the update:title event convention
Example fix
// before
model: {
prop: 'checked',
event: 'change',
},
props: ['checked'],
// after
props: ['modelValue'],
emits: ['update:modelValue'],
methods: {
onInput(e) { this.$emit('update:modelValue', e.target.value) },
} Defensive patterns
Strategy: validation
Validate before calling
# find custom v-model options
grep -rnE "^\s*model: *\{" --include='*.vue' src Prevention
- Author v-model components with modelValue + update:modelValue from day one on Vue 3
- If you keep the model option transitionally, set allowVue3Compat and match the exact compat shape
When it happens
Trigger: A Vue component options object (is_vue_component_options_object) declares a `model` property, and either allowVue3Compat is false or the option's prop/event pair is not exactly modelValue/update:modelValue (or the kebab model-value variant).
Common situations: Form/input wrapper components migrated from Vue 2 that customized v-model's prop name; after upgrade the component accepts `checked` in code but templates using v-model bind to modelValue, causing undefined values with no error.
Related errors
- Object declaration on `data` property is deprecated.
- The `{deprecated}` lifecycle hook is deprecated. Use `{repla
- `model` definition is deprecated. You may use the Vue 3-comp
- `$delete` and `$set` are deprecated.
- The Events api `{}` is deprecated.
AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20).
Data as JSON: /api/errors/d493f09f17bcdcbf.
Report an issue: GitHub.