{"record":{"id":"0eb0887d62f6090b","repo":"oxc-project/oxc","slug":"key-name-is-reserved","errorCode":null,"errorMessage":"Key `{name}` is reserved.","messagePattern":"Key `(.+?)` is reserved\\.","errorType":"validation","errorClass":"OxcDiagnostic","httpStatus":null,"severity":"warning","filePath":"crates/oxc_linter/src/rules/vue/no_reserved_keys.rs","lineNumber":53,"sourceCode":"    \"$refs\",\n    \"$isServer\",\n    \"$attrs\",\n    \"$listeners\",\n    \"$watch\",\n    \"$set\",\n    \"$delete\",\n    \"$on\",\n    \"$once\",\n    \"$off\",\n    \"$emit\",\n    \"$mount\",\n    \"$forceUpdate\",\n    \"$nextTick\",\n    \"$destroy\",\n];\n\nfn reserved_key_diagnostic(name: &str, span: Span) -> OxcDiagnostic {\n    OxcDiagnostic::warn(format!(\"Key `{name}` is reserved.\")).with_label(span)\n}\n\nfn starts_with_underscore_diagnostic(key: &str, group: &str, span: Span) -> OxcDiagnostic {\n    OxcDiagnostic::warn(format!(\"Key `{key}` is reserved in `{group}` group.\")).with_label(span)\n}\n\n#[derive(Debug, Default, Clone, Serialize, Deserialize, JsonSchema)]\n#[serde(rename_all = \"camelCase\", default, deny_unknown_fields)]\nstruct NoReservedKeysConfig {\n    /// Extra reserved key names to disallow, on top of the built-in list.\n    reserved: Vec<CompactStr>,\n    /// Extra component option groups to inspect, on top of the built-in\n    /// `props` / `computed` / `data` / `asyncData` / `methods` / `setup`.\n    groups: Vec<CompactStr>,\n}\n\n#[derive(Debug, Default, Clone, Serialize, Deserialize, JsonSchema)]\npub struct NoReservedKeys(Box<NoReservedKeysConfig>);","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/oxc-project/oxc/blob/e1e7af627c8843ab64044ed466b128fcc21a035b/crates/oxc_linter/src/rules/vue/no_reserved_keys.rs#L35-L71","documentation":"The vue/no-reserved-keys rule reports keys in component options that collide with Vue instance properties — the built-in list in the source starts with `$` (`$delete`, `$on`, `$once`, `$off`, `$emit`, `$mount`, `$forceUpdate`, `$nextTick`, `$destroy`). Vue proxies `$`-prefixed instance properties and methods, so declaring such a key in `props`/`data`/`computed`/`methods`/`setup` leads to shadowing or hard-to-debug lookup failures. Extra names can be added via the rule's `reserved` config array.","triggerScenarios":"Defining a `$`-prefixed key (or any name in your configured `reserved` list) inside the built-in groups `props` / `computed` / `data` / `asyncData` / `methods` / `setup`, or any group added via the rule's `groups` config.","commonSituations":"Styling/theming objects like `$theme` in data; methods mirroring the old events API (`$on`, `$emit`-style names); porting jQuery-era `$`-prefixed conventions into Vue options; teams extending the `reserved` list and hitting newly added entries.","solutions":["Rename the key to drop the `$` prefix (e.g. `$theme` -> `theme`).","If the name came from your own `reserved` config, reconcile the config with the component.","Keep `emit` calls on the instance (`this.$emit(...)`) rather than defining keys with `$` names.","Re-run oxlint to verify."],"exampleFix":"// before\nexport default {\n  data() {\n    return { $bus: null } // Key `$bus` is reserved.\n  }\n}\n\n// after\nexport default {\n  data() {\n    return { bus: null }\n  }\n}","handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["Reserve the `$` prefix for Vue instance properties and methods; never declare `$`-prefixed keys in option groups.","Extend the rule's `reserved` list with your framework's instance names (e.g. `$router`, `$store`).","Drop jQuery-style `$` naming conventions when porting code into Vue options."],"tags":["vue","naming","lint","reserved-keys","options-api"],"backgroundTag":"reserved-name-collision","analyzedSha":"e1e7af627c8843ab64044ed466b128fcc21a035b","analyzedAt":"2026-08-20T07:01:07.079Z","contentChangedAt":"2026-08-20T07:01:07.079Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}