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.

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.