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

  1. Move the `defineExpose(...)` / `context.expose(...)` call to the top of setup, before the first `await`.
  2. 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.
  3. Consider moving async work into `onMounted` or a composable so setup stays synchronous.
  4. 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

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

Related errors


AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20). Data as JSON: /api/errors/2ca2490272dd6e20. Report an issue: GitHub.