oxc-project/oxc · warning · OxcDiagnostic
Prefer top-level await over an async function call.
Error message
Prefer top-level await over an async function call.
What it means
This is the async-function-call diagnostic of oxlint's `unicorn/prefer-top-level-await`. It fires when a module top-level statement calls an async function (a function declared `async`, or returning a promise) without awaiting it — the floating-promise pattern — and suggests adding `await` before the call ('Add `await` before the function call.').
Source
Thrown at crates/oxc_linter/src/rules/unicorn/prefer_top_level_await.rs:23
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::{GetSpan, Span};
use crate::{
AstNode, ast_util::is_method_call, ast_util::variable_declaration_kind, context::LintContext,
rule::Rule,
};
fn prefer_top_level_await_over_promise_chain_diagnostic(span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("Prefer top-level await over using a promise chain.").with_label(span)
}
fn prefer_top_level_await_over_async_iife_diagnostic(span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("Prefer top-level await over using an async IIFE.").with_label(span)
}
fn prefer_top_level_await_over_async_function_call_diagnostic(span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("Prefer top-level await over an async function call.")
.with_help("Add `await` before the function call.")
.with_label(span)
}
#[derive(Debug, Default, Clone)]
pub struct PreferTopLevelAwait;
declare_oxc_lint!(
/// ### What it does
///
/// Prefer top-level await over top-level promises and async function calls.
///
/// ### Why is this bad?
///
/// Top-level await is more readable and can prevent unhandled rejections.
///
/// ### Examples
///View on GitHub (pinned to e1e7af627c)
Solutions
- Add `await`: `await init();`.
- If fire-and-forget is intentional, make it explicit with `void init();` (many configs accept `void`) or attach `.catch()` to handle rejection, then disable the rule for that line.
- If other top-level code should not block, restructure so dependents import a promise and await it themselves.
- For CJS files where TLA is unavailable, disable `unicorn/prefer-top-level-await`.
Example fix
// before init(); // after await init();
Defensive patterns
Strategy: validation
Validate before calling
// Make floating async calls explicit await init(); // blocking, ordered void init(); // intentional fire-and-forget init().catch(log); // fire-and-forget with rejection handling
Type guard
// Narrow before calling at top level: is it actually async?
function returnsPromise(fn) {
return typeof fn === 'function' && fn.constructor.name === 'AsyncFunction';
} Prevention
- Never call an async initializer bare at module top level — await it or void it.
- Use `void` (or `.catch`) to document intentional fire-and-forget so both readers and the rule see intent.
- Order top-level awaits to match dependency needs; importers block on your module until they settle.
When it happens
Trigger: A top-level expression statement or initializer whose callee is an `async` function declaration/identifier invoked without `await` (e.g. `init();` where `async function init() {}`); the rule matches the call via method/identifier checks at module scope.
Common situations: Bootstrap scripts calling `connect();` or `warmCache();` that are actually async — the module finishes evaluating before the work completes, causing races with imports that depend on the side effect. Common when converting scripts to ESM where ordering guarantees of top-level await matter.
Related errors
- Prefer top-level await over using a promise chain.
- Prefer top-level await over using an async IIFE.
- Promises which return async assertions must be awaited.
- Expect in a promise chain must be awaited or returned
- Prefer `Blob#{good_method}()` over `FileReader#{bad_method}(
AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20).
Data as JSON: /api/errors/08c0d365a8153c82.
Report an issue: GitHub.