Deploy Error Decoder

'Cannot use import statement outside a module' — fix Node ESM

Quick answer: Cannot use import statement outside a module means Node loaded your file as CommonJS but it uses ESM import syntax. Pick one module system: set "type": "module" in package.json (or use a .mjs extension) to run it as ESM, or convert the imports to require for CommonJS. Don't mix the two in one file.

Not your exact error? Paste it into the Deploy Error Decoder →

What the error looks like

Node throws a SyntaxError before your code even runs:

import express from 'express';
^^^^^^
SyntaxError: Cannot use import statement outside a module

# the inverse, requiring an ESM-only package from CJS:
Error [ERR_REQUIRE_ESM]: require() of ES Module not supported

Node decides a .js file is CommonJS unless told otherwise. ESM import in a CommonJS file is a syntax error; require() of an ESM-only package is the mirror-image failure.

Why it happens

No "type": "module"

A .js file defaults to CommonJS, so its import statements are invalid.

Mixing import and require

One file uses both syntaxes; Node can't be both module systems at once.

A dependency went ESM-only

A package you require() is now ESM-only and can't be loaded with require.

ts-node / Jest config

Tooling transpiles or resolves modules differently than your runtime expects.

Pick a lane in three steps

1

Decide: ESM or CommonJS

# Going ESM (modern): keep your 'import' syntax.
# Staying CommonJS: switch to require().  Don't half-and-half.
2

Tell Node which one

// package.json for ESM
{ "type": "module" }
// or just name the file server.mjs
// for CommonJS, use: const express = require('express');
3

Load ESM-only deps from CJS

// if you must stay CommonJS but a dep is ESM-only:
const mod = await import('that-esm-package');   // dynamic import
The real fix

Commit to one module system across the project

The lasting fix is consistency. Choose ESM (type: module + import everywhere) or CommonJS (require everywhere), align your TypeScript module/target and test runner to match, and use dynamic import() as the bridge when a single dependency forces the other system.

How Infraveil handles this

A broken start, caught before production

A module-system mismatch makes the app fail to start — which should never surprise you in production. Infraveil verifies a deploy before it runs on your own servers, so a process that won't boot is caught at the gate. Releases are approval-gated and recorded, with one-click rollback to the last version that started.

Deploys are verified before they run — a non-booting build is caught early
One-click rollback to the last release that started cleanly
Every deploy recorded, on servers you control

Frequently asked questions

What does 'Cannot use import statement outside a module' mean?

Node parsed your file as CommonJS, but it contains ESM import syntax, which is only valid in modules. You need to tell Node the file is a module, or use require instead.

How do I make Node treat my files as ES modules?

Add "type": "module" to package.json, or give the file an .mjs extension. Then import syntax is valid.

What is ERR_REQUIRE_ESM?

The opposite problem: you used require() on a package that is ESM-only. Either switch your project to ESM, or load it with a dynamic import().

Can I mix import and require?

Not in the same file. Pick one module system per project; use dynamic import() from CommonJS only as a bridge to an ESM-only dependency.

Free tools for this

Client-side, no signup — they run in your browser.

Stay in the loop

New backend-ops guides, free tools, and control-plane updates — no spam, unsubscribe anytime.