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.

Related guides

Tired of flaky CI? Latchkey auto-heals failed jobs and retries them for you. Start free →