{"record":{"id":"cde7328c9552322b","repo":"oxc-project/oxc","slug":"top-level-await-prevents-this-module-from-being","errorCode":null,"errorMessage":"Top-level `await` prevents this module from being loaded with `require(esm)`.","messagePattern":"Top-level `await` prevents this module from being loaded with `require\\(esm\\)`\\.","errorType":"validation","errorClass":"OxcDiagnostic","httpStatus":null,"severity":"warning","filePath":"crates/oxc_linter/src/rules/node/no_top_level_await.rs","lineNumber":15,"sourceCode":"use oxc_ast::AstKind;\nuse oxc_diagnostics::OxcDiagnostic;\nuse oxc_macros::declare_oxc_lint;\nuse oxc_span::Span;\nuse schemars::JsonSchema;\nuse serde::{Deserialize, Serialize};\n\nuse crate::{\n    AstNode,\n    context::LintContext,\n    rule::{DefaultRuleConfig, Rule},\n};\n\nfn no_top_level_await_diagnostic(span: Span) -> OxcDiagnostic {\n    OxcDiagnostic::warn(\"Top-level `await` prevents this module from being loaded with `require(esm)`.\")\n        .with_help(\"Move the `await` inside an `async` function, as ES modules with top-level `await` cannot be loaded with `require(esm)`.\")\n        .with_note(\"This rule is intended for published packages. Consider disabling it if this package is private.\")\n        .with_label(span)\n}\n\n#[derive(Debug, Default, Clone, Serialize, Deserialize, JsonSchema)]\n#[serde(rename_all = \"camelCase\", default, deny_unknown_fields)]\nstruct NoTopLevelAwaitConfig {\n    /// If `true`, top-level `await` is allowed in files that start with a\n    /// hashbang (`#!`), which marks them as executable scripts rather than\n    /// importable modules.\n    ignore_bin: bool,\n}\n\n#[derive(Debug, Default, Clone, Deserialize, Serialize)]\npub struct NoTopLevelAwait(NoTopLevelAwaitConfig);\n\ndeclare_oxc_lint!(","sourceCodeStart":1,"sourceCodeEnd":33,"githubUrl":"https://github.com/oxc-project/oxc/blob/e1e7af627c8843ab64044ed466b128fcc21a035b/crates/oxc_linter/src/rules/node/no_top_level_await.rs#L1-L33","documentation":"Diagnostic from oxlint rule node/no-top-level-await (restriction). Node.js v20.19 introduced require(esm), but an ES module containing top-level await cannot be loaded that way — require() throws ERR_REQUIRE_ASYNC_MODULE. The rule flags `await` expressions, `for await...of` loops, and `await using` declarations at module top level (any depth NOT nested in a function) so published packages stay loadable from both CommonJS and ESM consumers. The diagnostic's own note says it targets published packages; private apps may disable it.","triggerScenarios":"run() reports when a node is an AwaitExpression, a ForOfStatement with r#await == true, or a VariableDeclaration of await-using kind, AND no ancestor is a Function or ArrowFunctionExpression. Suppressed only when the ignoreBin option is true and the file starts with '#!' (an executable script, not an importable module). Triggers: 'const foo = await import(\"foo\");' or a top-level 'for await (const e of gen())'.","commonSituations":"Dual-format (CJS+ESM) libraries preparing for require(esm) on Node 20.19+/22; top-level await used for config/db initialization during ESM migration; executable scripts with a hashbang that legitimately top-level-await (use ignoreBin); private apps where the constraint is irrelevant.","solutions":["Move the awaited work into an exported async function the caller invokes: export async function init() { ... }","Initialize lazily: export a promise or an init() rather than awaiting at module load","For executable scripts, keep the hashbang and configure { \"ignoreBin\": true }","For private apps never loaded via require(), disable the rule in .oxlintrc.json as the diagnostic note suggests"],"exampleFix":"// before (top level of module)\nconst foo = await import('foo');\n\n// after\nexport async function load() {\n  const foo = await import('foo');\n  return foo;\n}","handlingStrategy":"validation","validationCode":"// .oxlintrc.json\n\"rules\": { \"node/no-top-level-await\": [\"error\", { \"ignoreBin\": true }] }\n\n// pre-publish gate for dual-format packages\nnpx oxlint -c .oxlintrc.json --deny-warning . && npm publish --dry-run","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Design package entry points as synchronous module definitions plus exported async init() functions","If your repo mixes apps and published packages, scope this rule to the package directories via overrides","In CI, additionally smoke-require built ESM output from a CJS harness to catch ERR_REQUIRE_ASYNC_MODULE before release"],"tags":["node","esm","commonjs","async","packaging","oxlint"],"backgroundTag":"top-level-await-esm","analyzedSha":"e1e7af627c8843ab64044ed466b128fcc21a035b","analyzedAt":"2026-08-20T07:01:07.079Z","contentChangedAt":"2026-08-20T07:01:07.079Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}