Skip to content
Latchkey

Jest "Cannot use import statement outside a module" (ESM)

Jest hit raw ESM import syntax it never compiled to CommonJS. Usually an ESM-only dependency is skipped by the default transformIgnorePatterns, or no transform is configured for your own files.

What this error means

A suite fails to parse with "SyntaxError: Cannot use import statement outside a module," pointing at a file inside node_modules (an ESM-only package) or at your own untransformed TS/JSX source.

jest
/app/node_modules/nanoid/index.js:1
export { nanoid } from './index.browser.js';
^^^^^^

SyntaxError: Cannot use import statement outside a module

Diagnose it: flake, environment, or genuine failure?

Before debugging the assertion, establish whether the test is deterministic. A test that fails only in CI is usually order-dependent, time-dependent, or racing something, and fixing the assertion will not help.

Terminal
# does it fail in isolation?
npx vitest run path/to/file.test.ts

# is it order dependent? run the suite in a random order twice
npx vitest run --sequence.shuffle

# is it a race? run the same file repeatedly
for i in $(seq 1 20); do npx vitest run path/to/file.test.ts || break; done

Common causes

ESM-only dependency not transformed

Jest ignores node_modules by default. An ESM-only package (nanoid, uuid, query-string) is loaded as-is and its import breaks under CommonJS.

No transform for your own source

Without babel-jest or ts-jest configured, Jest cannot compile your own import/TSX either and throws the same SyntaxError on source files.

How to fix it

Allow-list the ESM package for transform

Carve the ESM dependency out of transformIgnorePatterns so Jest compiles it instead of skipping it.

jest.config.js
// jest.config.js
module.exports = {
  transformIgnorePatterns: ['/node_modules/(?!(nanoid|uuid|query-string)/)'],
};

Configure a transform for your code

  1. Add babel-jest with @babel/preset-env (plus preset-typescript/preset-react as needed).
  2. Or use ts-jest for TypeScript projects.
  3. Confirm the transform glob covers every source extension you import.

CI-only causes worth ruling out

  • Runners have fewer cores than a laptop, so timing-sensitive tests that pass locally fail under contention.
  • No TTY and a different locale or timezone. Snapshot tests containing formatted dates or numbers are the usual casualty; pin TZ and LANG in the job.
  • Parallel workers sharing a database, a port, or a temp directory. Give each worker its own namespace.
  • Default timeouts calibrated on a fast machine. A cold runner is slower on first execution, especially before any cache warms.

How to prevent it

  • Update transformIgnorePatterns as ESM-only deps are added.
  • Standardize on babel-jest or ts-jest for the whole repo.
  • Consider Vitest for ESM-first projects to avoid transform config.

Frequently asked questions

What causes Jest "Cannot use import statement outside a module" (ESM)?
There are 2 common causes: esm-only dependency not transformed and no transform for your own source. Jest ignores node_modules by default.
How do I fix Jest "Cannot use import statement outside a module" (ESM)?
There are 2 fixes depending on which cause you have: allow-list the esm package for transform and configure a transform for your code. Work through them in order, since the first is the most common.
What does Jest "Cannot use import statement outside a module" (ESM) actually mean?
A suite fails to parse with "SyntaxError: Cannot use import statement outside a module," pointing at a file inside node_modules (an ESM-only package) or at your own untransformed TS/JSX source.
How do I stop Jest "Cannot use import statement outside a module" (ESM) happening again?
Update transformIgnorePatterns as ESM-only deps are added. The prevention section lists 3 changes that keep it from recurring.

Related guides

References

Not every red build is your code. Latchkey repairs the ones that are not, on the runner. Start free → 30-day trial · No credit card