oxc-project/oxc · error · OxcDiagnostic
The ` ` lifecycle hook is deprecated. Use ` ` instead.
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.
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
- `model` definition is deprecated.
- Object declaration on `data` property is deprecated.
- `$delete` and `$set` are deprecated.
- `model` definition is deprecated. You may use the Vue…
- Props default value factory functions no longer have access…
AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20).
Data as JSON: /api/errors/611fa89862904b88.
Report an issue: GitHub.
Appendix: 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)