{"record":{"id":"22466e10b2a53bc3","repo":"oxc-project/oxc","slug":"lifecycle-hook-hook-name-is-called-after-awai","errorCode":null,"errorMessage":"Lifecycle hook `{hook_name}` is called after `await` in `setup()`.","messagePattern":"Lifecycle hook `(.+?)` is called after `await` in `setup\\(\\)`\\.","errorType":"validation","errorClass":"OxcDiagnostic","httpStatus":null,"severity":"error","filePath":"crates/oxc_linter/src/rules/vue/no_lifecycle_after_await.rs","lineNumber":21,"sourceCode":"    ast::{\n        AwaitExpression, CallExpression, ExportDefaultDeclarationKind, Expression, Function,\n        ObjectExpression,\n    },\n};\nuse oxc_ast_visit::{VisitJs, walk_js};\nuse oxc_diagnostics::OxcDiagnostic;\nuse oxc_macros::declare_oxc_lint;\nuse oxc_semantic::{ScopeFlags, Scoping, SymbolId};\nuse oxc_span::Span;\nuse rustc_hash::FxHashMap;\n\nuse crate::module_record::{ImportEntry, ImportImportName};\nuse crate::{\n    AstNode, context::LintContext, frameworks::FrameworkOptions, rule::Rule, utils::find_property,\n};\n\nfn no_lifecycle_after_await_diagnostic(span: Span, hook_name: &str) -> OxcDiagnostic {\n    OxcDiagnostic::warn(format!(\n        \"Lifecycle hook `{hook_name}` is called after `await` in `setup()`.\"\n    ))\n    .with_help(\"Lifecycle hooks should be called synchronously in `setup()`. Move the hook call before the first `await`.\")\n    .with_label(span)\n}\n\n#[derive(Debug, Default, Clone)]\npub struct NoLifecycleAfterAwait;\n\ndeclare_oxc_lint!(\n    /// ### What it does\n    ///\n    /// Disallow asynchronously registered lifecycle hooks.\n    ///\n    /// ### Why is this bad?\n    ///\n    /// Lifecycle hooks must be registered synchronously during `setup()` execution.\n    /// If a lifecycle hook is called after an `await` statement, it may be registered","sourceCodeStart":3,"sourceCodeEnd":39,"githubUrl":"https://github.com/oxc-project/oxc/blob/e1e7af627c8843ab64044ed466b128fcc21a035b/crates/oxc_linter/src/rules/vue/no_lifecycle_after_await.rs#L3-L39","documentation":"The vue/no-lifecycle-after-await rule fires when a Vue lifecycle hook (`onMounted`, `onUnmounted`, ...) is registered after an `await` inside `setup()` / `<script setup>`. Lifecycle registration is synchronous: once the first `await` yields, the component may already be mounted, so a hook registered afterwards will never be invoked. The rule resolves imported hook names through the module record (ImportEntry/ImportImportName) so aliased and re-exported hook imports are matched too.","triggerScenarios":"`await fetch(...); onMounted(() => {...});` in `<script setup>`, or the equivalent in a `setup()` function. Any awaited promise followed by an `on*` hook call within the same async setup scope.","commonSituations":"Components that fetch data at the top of setup before subscribing to lifecycle events; refactors that introduce top-level await (Suspense-based components); copy-pasting hook registration below newly added async initialization.","solutions":["Move every `onMounted`/`onUnmounted`/... call above the first `await` in setup.","If the hook callback needs awaited data, keep registration synchronous and reference a reactive ref that is filled in later.","Move the async work into `onMounted` or a `watchEffect` so setup remains synchronous.","Re-run oxlint to confirm hook calls precede all awaits."],"exampleFix":"// before\n<script setup>\nconst user = await getUser();\nonMounted(() => console.log(user.name)); // called after `await`\n</script>\n\n// after\n<script setup>\nconst user = ref(null);\nonMounted(async () => {\n  user.value = await getUser();\n  console.log(user.value.name);\n});\n</script>","handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["Register all lifecycle hooks at the top of setup, before any await.","Keep setup synchronous; move async work into onMounted or watchEffect.","Enable vue/no-lifecycle-after-await in CI to catch reordering during refactors.","Be extra careful when adding top-level await (Suspense components) to existing setups."],"tags":["vue","async-await","lifecycle","lint","script-setup"],"backgroundTag":"async-setup-order","analyzedSha":"e1e7af627c8843ab64044ed466b128fcc21a035b","analyzedAt":"2026-08-20T07:01:07.079Z","contentChangedAt":"2026-08-20T07:01:07.079Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}