oxc-project/oxc · warning · OxcDiagnostic
`{name}` is forbidden after an `await` expression.
Error message
`{name}` is forbidden after an `await` expression. What it means
The vue/no-expose-after-await rule fires when `expose()` (Options API `setup(context)`) or `defineExpose()` (`<script setup>`) is called after an `await` expression in async setup logic. Vue resolves the component's exposed object during synchronous setup; exposing after an await means the parent may already hold a reference and the exposed contract is not in place. The rule's help text directs you to move the call before the first `await`.
Source
Thrown at crates/oxc_linter/src/rules/vue/no_expose_after_await.rs:18
use oxc_ast::{
AstKind,
ast::{
ArrowFunctionExpression, AwaitExpression, BindingPattern, CallExpression, ChainElement,
ExportDefaultDeclarationKind, Expression, Function, ObjectExpression, ObjectPropertyKind,
Program, Statement,
},
};
use oxc_ast_visit::{VisitJs, walk_js};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_semantic::{ScopeFlags, Scoping, SymbolId};
use oxc_span::Span;
use crate::{AstNode, context::LintContext, frameworks::FrameworkOptions, rule::Rule};
fn no_expose_after_await_diagnostic(span: Span, name: &str) -> OxcDiagnostic {
OxcDiagnostic::warn(format!("`{name}` is forbidden after an `await` expression."))
.with_help(
"`expose` should be called synchronously in `setup()` \
(or `defineExpose()` in `<script setup>`). Move the call before the first `await`.",
)
.with_label(span)
}
#[derive(Debug, Default, Clone)]
pub struct NoExposeAfterAwait;
declare_oxc_lint!(
/// ### What it does
///
/// Disallow asynchronously registered `expose`.
///
/// ### Why is this bad?
///
/// `defineExpose` and `context.expose()` registered after an `await`View on GitHub (pinned to e1e7af627c)
Solutions
- Move the `defineExpose(...)` / `context.expose(...)` call to the top of setup, before the first `await`.
- If the exposed values depend on awaited data, expose stable references (e.g. a reactive object or methods) up front and mutate them after the await completes.
- Consider moving async work into `onMounted` or a composable so setup stays synchronous.
- Re-run oxlint to confirm the call now precedes every await.
Example fix
// before
<script setup>
const data = await loadData();
defineExpose({ data }); // forbidden after an `await` expression
</script>
// after
<script setup>
const data = ref(null);
defineExpose({ data });
data.value = await loadData();
</script> Defensive patterns
Strategy: validation
Prevention
- Treat 'defineExpose/expose first, await later' as a hard ordering rule in setup.
- Expose refs/methods up front and fill data after awaits complete.
- Enable vue/no-expose-after-await in CI so reordering mistakes fail the build.
- Review any PR that introduces top-level await into setup.
When it happens
Trigger: In `<script setup>`: `await fetch(...); defineExpose({ reload });`. In Options API `setup()`: `await something(); context.expose({ ... })`. The rule resolves the callee symbol (ScopeFlags/SymbolId are used to match the call) so any awaited statement followed by expose/defineExpose triggers it.
Common situations: Data-fetching components that load remote config before exposing methods; refactoring sync setup into async without reordering; components using top-level await in `<script setup>` (which requires Suspense).
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Lifecycle hook `{hook_name}` is called after `await` in `set
- [HIRBuilder] expected block {:?} to exist
- Inline helpers are not supported yet
- TS5042
- TS5081
AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20).
Data as JSON: /api/errors/2ca2490272dd6e20.
Report an issue: GitHub.