Skip to content
Latchkey

Node "Cannot use import statement outside a module" - Fix ESM Config in CI

This SyntaxError means Node tried to run a file containing ESM import syntax as CommonJS. Node decides the module system from package.json "type" and file extension - if it picks CJS, top-level import is a syntax error.

What this error means

A script or test crashes at parse time with SyntaxError: Cannot use import statement outside a module. The file uses import, but Node is treating it as CommonJS because nothing told it the file is ESM.

Node output
import { foo } from './foo.js'
^^^^^^
SyntaxError: Cannot use import statement outside a module
    at internalCompileFunction (node:internal/vm)

Common causes

No "type":"module" and a .js file using import

Without "type": "module" in package.json, Node treats .js as CommonJS, so ESM import syntax is rejected.

Running uncompiled TypeScript/ESM directly under CJS

Executing source that uses import with a CJS-configured Node (no loader, no build) parses it as CommonJS and fails.

How to fix it

Declare the module system explicitly

Mark the package as ESM, or rename ESM files to .mjs.

package.json
// package.json
{ "type": "module" }
# or name the entry file index.mjs
# or, to stay CJS, compile import->require with your bundler/tsc

Run ESM correctly in CI

  1. For ESM projects, set "type": "module" and use .js as ESM (or .mjs).
  2. For mixed projects, keep CJS files as .cjs and ESM as .mjs.
  3. For TypeScript, build to the target module format, or use a loader (tsx/ts-node ESM).

How to prevent it

  • Declare "type" explicitly and use matching extensions.
  • Compile or load TypeScript before running under Node.
  • Keep one module system per package.

Related guides

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