oxc-project/oxc · error · OxcDiagnostic
The `{deprecated}` lifecycle hook is deprecated. Use `{repla
Error message
The `{deprecated}` lifecycle hook is deprecated. Use `{replacement}` instead. What it means
Diagnostic from oxlint's vue/no-deprecated-destroyed-lifecycle rule (since oxlint 1.35.0). It fires when a component uses the Vue 2 lifecycle hooks `destroyed` or `beforeDestroy`: in Vue 3 they were renamed to `unmounted` and `beforeUnmount`, and the old names are silently never invoked, so cleanup code simply stops running (leaks, lingering listeners). The message and help text interpolate the deprecated hook and its replacement.
Source
Thrown at crates/oxc_linter/src/rules/vue/no_deprecated_destroyed_lifecycle.rs:20
AstKind,
ast::{
CallExpression, ExportDefaultDeclarationKind, Expression, ObjectExpression,
ObjectPropertyKind, PropertyKey,
},
};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::Span;
use rustc_hash::FxHashSet;
use crate::{context::LintContext, rule::Rule};
fn no_deprecated_destroyed_lifecycle_diagnostic(
span: Span,
deprecated: &str,
replacement: &str,
) -> OxcDiagnostic {
OxcDiagnostic::warn(format!(
"The `{deprecated}` lifecycle hook is deprecated. Use `{replacement}` instead."
))
.with_help(format!("Replace `{deprecated}` with `{replacement}`."))
.with_label(span)
}
#[derive(Debug, Default, Clone)]
pub struct NoDeprecatedDestroyedLifecycle;
declare_oxc_lint!(
/// ### What it does
///
/// Disallow using deprecated `destroyed` and `beforeDestroy` lifecycle hooks in Vue.js 3.0.0+.
///
/// ### Why is this bad?
///
/// In Vue.js 3.0.0+, the `destroyed` and `beforeDestroy` lifecycle hooks have been renamed
/// to `unmounted` and `beforeUnmount` respectively. Using the old names is deprecated andView on GitHub (pinned to e1e7af627c)
Solutions
- Rename beforeDestroy to beforeUnmount
- Rename destroyed to unmounted
- Add this rule to the migration lint set so every renamed hook is caught in one pass
Example fix
// before
beforeDestroy() { this.unsubscribe() },
destroyed() { this.teardown() },
// after
beforeUnmount() { this.unsubscribe() },
unmounted() { this.teardown() }, Defensive patterns
Strategy: validation
Validate before calling
# find Vue 2 destroy lifecycle hooks
grep -rnE "\b(beforeDestroy|destroyed)\s*\(" --include='*.vue' src Prevention
- Use beforeUnmount/unmounted names from the start of any Vue 3 project
- After renaming, test teardown paths (route away, unmount) to confirm cleanup actually runs
When it happens
Trigger: A component options object declares a `destroyed` or `beforeDestroy` property (tracked in a FxHashSet of deprecated hook names with their replacements).
Common situations: Components migrated from Vue 2 that keep teardown in destroyed(); nothing crashes, but timers, event listeners, and observers are never cleaned up, producing slow memory leaks that only show up in long sessions.
Related errors
- Object declaration on `data` property is deprecated.
- `model` definition is deprecated.
- `$delete` and `$set` are deprecated.
- The Events api `{}` is deprecated.
- `model` definition is deprecated. You may use the Vue 3-comp
AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20).
Data as JSON: /api/errors/611fa89862904b88.
Report an issue: GitHub.