oxc-project/oxc · warning · OxcDiagnostic

Unexpected `await` inside a loop.

Error message

Unexpected `await` inside a loop.

What it means

Diagnostic from the oxlint rule `no-await-in-loop` (crates/oxc_linter/src/rules/eslint/no_await_in_loop.rs). It reports an `await` expression appearing in the body of a `for`, `for-in`, `for-of`, `while`, or `do-while` loop. Awaiting inside a loop serializes iterations, so total time is the sum of all awaited operations instead of running them concurrently; the rule's help text suggests collecting the promises and using `Promise.all()`.

Source

Thrown at crates/oxc_linter/src/rules/eslint/no_await_in_loop.rs:12

use oxc_ast::{
    AstKind,
    ast::{Expression, Statement, VariableDeclarationKind},
};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::{GetSpan, Span};

use crate::{AstNode, context::LintContext, rule::Rule};

fn no_await_in_loop_diagnostic(span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn("Unexpected `await` inside a loop.")
        .with_help("Collect all promises into an array and use `Promise.all()` to run them in parallel, rather than awaiting each one sequentially inside the loop.")
        .with_label(span)
}

#[derive(Debug, Default, Clone)]
pub struct NoAwaitInLoop;

declare_oxc_lint!(
    /// ### What it does
    ///
    /// This rule disallows the use of `await` within loop bodies. (for, for-in, for-of, while, do-while).
    ///
    /// ### Why is this bad?
    ///
    /// It potentially indicates that the async operations are not being effectively parallelized.
    /// Instead, they are being run in series, which can lead to poorer performance.
    ///
    /// ### Examples

View on GitHub (pinned to e1e7af627c)

Solutions

  1. If iterations are independent, map to promises and run concurrently: `await Promise.all(ids.map(id => save(id)));`.
  2. For bounded concurrency, use a worker-pool pattern (e.g. process chunks with `Promise.all` over slices) or p-limit style batching.
  3. If each iteration genuinely depends on the previous result (sequential requirement is intentional), suppress with `// oxlint-disable-next-line no-await-in-loop` on that line.
  4. Disable the rule per-directory in .oxlintrc.json if the codebase intentionally uses sequential awaits as a pattern (e.g. rate-limit compliance).

Example fix

// before
for (const url of urls) {
  const res = await fetch(url);
  results.push(res);
}

// after
const results = await Promise.all(urls.map(url => fetch(url)));
Defensive patterns

Strategy: fallback

Validate before calling

// Before committing, detect awaits directly inside loop bodies in changed files
const loopAwait = /(?:for\s*\(|while\s*\(|do\s*\{)/[Symbol.replace];
// simplest reliable gate: run oxlint on the diff and treat no-await-in-loop as blocking
execSync('oxlint --deny-warnings .');

Prevention

When it happens

Trigger: Any AwaitExpression nested inside the body (Statement list) of a ForStatement, ForInStatement, ForOfStatement, WhileStatement, or DoWhileStatement — e.g. `for (const id of ids) { await save(id); }`.

Common situations: Batch-processing API requests, saving database rows, or fetching per-key lookups in a loop; code written for correctness first and never parallelized; adopting oxlint's default `restriction`/eslint rule set on existing server code.

Related errors


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