Skip to content
Latchkey

Node "SyntaxError: top-level await is only available in ES modules" in CI

Top-level await (await outside any async function) is only valid in ES modules. In a CommonJS file Node parses await as a reserved word and throws a SyntaxError.

What this error means

A file using top-level await fails with "SyntaxError: Unexpected reserved word" or, with clearer messaging, "top-level await is only available in ES modules".

node
const res = await fetch(url);
            ^^^^^

SyntaxError: await is only valid in async functions and the top level bodies of modules

Common causes

Top-level await in a CommonJS file

The file is CommonJS (no "type": "module", .js extension), so await at module scope is a syntax error.

A tool compiled the module down to CommonJS

A build target of CommonJS strips ESM semantics, leaving top-level await invalid in the emitted output.

How to fix it

Make the file an ES module

Set "type": "module" or use the .mjs extension so top-level await is allowed.

package.json
{
  "type": "module"
}

Or wrap the await in an async IIFE

If the file must stay CommonJS, move the await into an async function and invoke it.

index.cjs
(async () => {
  const res = await fetch(url);
})();

How to prevent it

  • Use ESM where you rely on top-level await.
  • Keep the compiler module target as ESM if your source uses it.
  • Avoid top-level await in files that must remain CommonJS.

Frequently asked questions

What causes ""top-level await is only available in ES modules""?
The file is CommonJS (no "type": "module", .js extension), so await at module scope is a syntax error.
How do I fix "top-level await is only available in ES modules"?
Set "type": "module" or use the .mjs extension so top-level await is allowed.

Related guides

References

Latchkey auto-heals failures like this one - detected, fixed, and retried without you. Start free → 30-day trial · No credit card