oxc-project/oxc · warning · OxcDiagnostic

Prefer top-level await over using a promise chain.

Error message

Prefer top-level await over using a promise chain.

What it means

This is the promise-chain diagnostic of oxlint's `unicorn/prefer-top-level-await` rule. In an ES module (where top-level `await` is allowed), it flags promise chains like `fetch(url).then(...)` whose result is used at module top level, and recommends `await`ing the chain directly — removing scheduling indirection and letting you use try/catch and loops around async values.

Source

Thrown at crates/oxc_linter/src/rules/unicorn/prefer_top_level_await.rs:15

use oxc_ast::{
    AstKind,
    ast::{Expression, VariableDeclarationKind},
};
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
    ///

View on GitHub (pinned to e1e7af627c)

Solutions

  1. Add `await`: `const config = await (await fetch('/config.json')).json();`.
  2. Ensure the file is an ES module (`.mjs` or `"type": "module"`) and your runtime/bundler supports top-level await (Node >= 14.8 with ESM flag-free since 16).
  3. If the parallelism matters (multiple chains started concurrently), use `await Promise.all([...])` instead of sequential awaits.
  4. Disable the rule with `"unicorn/prefer-top-level-await": "off"` for CJS-flavored code.

Example fix

// before
const data = fetch(url).then((r) => r.json());

// after
const data = await (await fetch(url)).json();
Defensive patterns

Strategy: validation

Validate before calling

// In ESM, await module-scope async work directly
const config = await (await fetch('/config.json')).json();
// CI: npx oxlint --deny-warn unicorn/prefer-top-level-await src/

Try / catch

// Top-level await participates in normal try/catch at module scope
try {
  const config = await loadConfig();
} catch (err) {
  handleBootFailure(err);
}

Prevention

When it happens

Trigger: A top-level statement (typically `const x = promise.then(...)` — recognized via `variable_declaration_kind` and `is_method_call` for `.then`) in a module context, where the promise chain could be replaced by `const x = await promise...`. The rule only applies at the module top level, not inside functions.

Common situations: Config/module-init code like `const config = fetch('/config.json').then(r => r.json());` in ESM; migrating CommonJS scripts to ESM and modernizing `.then` chains. Requires the file to be a module (`"type": "module"`, `.mjs`, or ESM in the bundler) — in plain CJS scripts top-level await is a syntax error, so the rule's advice does not apply there.

Related errors


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