{"record":{"id":"3c882c3d1ab61ea1","repo":"oxc-project/oxc","slug":"top-level-await-is-not-available-in-the-configured","errorCode":null,"errorMessage":"Top-level await is not available in the configured target environment.","messagePattern":"Top-level await is not available in the configured target environment\\.","errorType":"validation","errorClass":"OxcDiagnostic","httpStatus":null,"severity":"warning","filePath":"crates/oxc_transformer/src/es2022/mod.rs","lineNumber":133,"sourceCode":"    fn enter_static_block(&mut self, block: &mut StaticBlock<'a>, ctx: &mut TraverseCtx<'a>) {\n        if let Some(class_properties) = &mut self.class_properties {\n            class_properties.enter_static_block(block, ctx);\n        }\n    }\n\n    fn exit_static_block(&mut self, block: &mut StaticBlock<'a>, ctx: &mut TraverseCtx<'a>) {\n        if let Some(class_properties) = &mut self.class_properties {\n            class_properties.exit_static_block(block, ctx);\n        }\n    }\n\n    fn enter_await_expression(\n        &mut self,\n        node: &mut AwaitExpression<'a>,\n        ctx: &mut TraverseCtx<'a>,\n    ) {\n        if self.options.top_level_await && Self::is_top_level(ctx) {\n            let warning = OxcDiagnostic::warn(\n                \"Top-level await is not available in the configured target environment.\",\n            )\n            .with_label(node.span);\n            ctx.state.error(warning);\n        }\n    }\n}\n\nimpl ES2022<'_> {\n    fn is_top_level(ctx: &TraverseCtx) -> bool {\n        ctx.current_hoist_scope_id() == ctx.scoping().root_scope_id()\n    }\n}\n","sourceCodeStart":115,"sourceCodeEnd":147,"githubUrl":"https://github.com/oxc-project/oxc/blob/e1e7af627c8843ab64044ed466b128fcc21a035b/crates/oxc_transformer/src/es2022/mod.rs#L115-L147","documentation":"Oxc's ES2022 transform emits this warning when it finds an `await` expression at module top level while the configured target environments do not support top-level await. The `top_level_await` flag is derived from a browserslist/engine target query (crates/oxc_transformer/src/options/env.rs:160) via `has_feature(ES2022TopLevelAwait)`, which returns true when at least one target engine lacks the feature and it therefore needs lowering. Oxc has no transform that lowers top-level await to older syntax, so it warns instead of silently emitting code that will fail at runtime in the target.","triggerScenarios":"Running the oxc transformer with a `targets`/browserslist query that includes engines without top-level await (e.g. `chrome >= 60`, older node, legacy safari), causing `ES2022Options::top_level_await` to be set, and then transforming a module whose top-level hoist scope contains an `AwaitExpression` (e.g. `const data = await fetch(url);` at module top level). The check is `enter_await_expression` in crates/oxc_transformer/src/es2022/mod.rs:127 — it fires only when `options.top_level_await && current_hoist_scope_id == root_scope_id`, so awaits inside functions are unaffected.","commonSituations":"Modernizing a codebase that uses top-level await for config/env loading while CI still pins `targets` to browserslist `defaults` or an old `.browserslistrc`; switching a bundler pipeline from esbuild/swc to oxc with copied-over legacy target lists; Node CLIs targeting Node < 14.8; shared library code consumed by both modern and legacy bundles. The internal comment at env.rs:76 notes that enabling this flag errors for ALL top-level awaits, so any single TLA usage trips it.","solutions":["Raise the target query so every engine supports top-level await (Chrome >= 89, Firefox >= 89, Safari >= 15, Node >= 14.8), e.g. `EnvOptions::from_target_list(&[\"chrome 89\",\"node 14.8\"])` or update .browserslistrc, so `has_feature(ES2022TopLevelAwait)` returns false","Remove the top-level await: move the await into an async function and call it (fire-and-forget or via an init function the entry point awaits)","If the warning is noise because a downstream bundler (esbuild/webpack) handles TLA itself, configure oxc to preserve the syntax (empty/modern targets) and let the bundler lower it","Wrap the async work in a dynamic-import chain: move the awaiting module behind `await import(\"./module.mjs\")` executed from an async entry"],"exampleFix":"// before (targets = chrome 60, module top level)\nconst config = await loadConfig();\nexport default config;\n\n// after (no TLA)\nasync function init() {\n  const config = await loadConfig();\n  return config;\n}\nexport default init(); // Promise; consumers do `await init()` or (await import(...))","handlingStrategy":"validation","validationCode":"// Before transforming, check whether any target lacks top-level await\nuse oxc_transformer::EnvOptions;\n\nlet env = EnvOptions::from_target_list(&[\"chrome 89\", \"firefox 89\", \"safari 15\", \"node 14.8\"])?;\n// If you cannot raise targets, scan the source for top-level await first:\nfn uses_top_level_await(src: &str) -> bool {\n    // cheap heuristic: parse with oxc_parser and walk Program-level\n    // statements for ExpressionStatement(AwaitExpression) or `for await`\n    oxc_parser::parse(src).program_has_top_level_await()\n}","typeGuard":"// TypeScript consumers: narrow the transform setup at compile time\ntype Targets = string[];\nconst TLA_SAFE: Targets = [\"chrome>=89\", \"firefox>=89\", \"safari>=15\", \"node>=14.8\"];\nfunction assertTlaSafe(targets: Targets): void {\n  // fail the build config early instead of per-file diagnostics\n  if (!TLA_SAFE.every(t => targets.some(x => x.startsWith(t.split(\">\")[0])))) {\n    throw new Error('targets include engines without top-level await');\n  }\n}","tryCatchPattern":"// Diagnostics are collected, not thrown: after running the transformer,\n// inspect the returned diagnostics and fail or gate on severity\nlet result = transformer.build(source);\nfor d in &result.errors {\n    if d.message.contains(\"Top-level await is not available\") {\n        // route to a legacy no-TLA build path or fail the target\n    }\n}","preventionTips":["Pin browserslist/engine targets to TLA-capable versions (chrome>=89, firefox>=89, safari>=15, node>=14.8) in the same PR that introduces top-level await","Keep an explicit allowlist in CI: grep new code for module-level `await ` when the legacy target matrix is still active","Treat this warning as a runtime breaker, not lint noise: the emitted code throws SyntaxError in engines without TLA","Document one async-init pattern (exported promise or `await import`) for the repo so contributors avoid ad-hoc top-level awaits"],"tags":["oxc","transformer","top-level-await","browserslist","targets","es2022"],"backgroundTag":"top-level-await-unsupported","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"}