Skip to main content
DevOps Insightsguides & answers

Node.js · troubleshooting

SyntaxError: Cannot use import statement outside a module

Node.js loaded your file as a CommonJS script, where import statements are not allowed. Usually the package is not marked as an ES module, the Node.js version is older than automatic detection, or a tool runs the file as CommonJS.

Reproduced on Node.js 25.9.0, . Where the text says “reproduced”, the behaviour was run on that version, not taken from documentation.

First published

New to this? Read what is actually happening first, then come back to the steps.

On this page · 8 sections

Before you start

  • Your Node.js version (node -v) and the nearest package.json to the file.

Run this first

step 1 of 1
node -v; node -p "require('./package.json').type"

Look for Node.js older than 22.7.0, or a type of commonjs

The two things that decide how a .js file is loaded.

Work out which cause you have

A few questions to narrow the list. Every answer ends in a command that confirms or rules the cause out — this cannot see your cluster, so nothing here is a certainty until you have checked.

Narrow it down

0 answered · nothing is sent anywhere

What does node -p "require('./package.json').type" print?

Cause space

3 of 3 still possible

  • The package is not marked as an ES module, on a Node.js without detectionCommon
  • package.json says "type": "commonjs"Occasional
  • A tool runs the file as CommonJSOccasional

Nothing ruled out yet. Answer the question above and the branches your answer eliminates will strike through here.

Or diagnose it manually

In this order. The first command usually contains the whole answer.

  1. Step 1

    node -v; node -p "require('./package.json').type"

    The two things that decide how a .js file is loaded.

    Look for Node.js older than 22.7.0, or a type of commonjs

Every cause, and how to fix it

Ordered by how often each one turns out to be the answer.

The package is not marked as an ES module, on a Node.js without detection

Common

Without "type": "module", a .js file is CommonJS. Node.js before 22.7.0 (or 20.19.0 on the 20 line) does not look at the code to decide otherwise.

Confirm

node -v; node -p "require('./package.json').type"

An older Node.js, and undefined or commonjs as the type

Fix

  • Add "type": "module" to package.json, then rename any file that still uses require() to .cjs.
  • Or rename just this file to .mjs.
  • Upgrading Node.js also helps, but set the type anyway: detection costs a reparse and prints a warning.

package.json says "type": "commonjs"

Occasional

An explicit commonjs type turns detection off, so even the newest Node.js treats import as an error.

Confirm

node -p "require('./package.json').type"

commonjs: the package is declared CommonJS, so detection never runs

Fix

  • Change it to module if the package is meant to be ES modules, or use .mjs for the files that use import.

A tool runs the file as CommonJS

Occasional

Test runners, TypeScript runners and bundlers can load files themselves, in CommonJS mode, whatever Node.js would do. Not reproduced here; the error then comes from the tool's own loader.

Confirm

node path/to/file.js

It runs under plain node but fails under the tool, which points at the tool's module setting

Fix

  • Configure the tool for ES modules (its own ESM option), or have it transform the file, following the tool's documentation.

Understanding it properly

Skip this if you are mid-incident — the working part of the page is above. Worth reading afterwards, because understanding the mechanism is what stops the next one.

In plain terms

Node.js has two module systems. CommonJS uses require(); ES modules use import. Node decides which one a .js file is from the nearest package.json, the file extension and, in newer versions, by looking at the code. When it treats an import file as CommonJS, it stops at the first import line.

Words used on this page

ES module
JavaScript's standard module format, with import and export.
CommonJS
Node's original module format, with require() and module.exports.
"type": "module"
A package.json field that makes every .js file in that package an ES module; .mjs and .cjs extensions override it per file.
What is actually happening

Reproduced on 22 October 2026 with the same file on two Node.js versions. Node.js 18.19.1 refused it with "SyntaxError: Cannot use import statement outside a module", after a warning to set "type": "module" in package.json or use the .mjs extension.

Node.js 25.9.0 ran the same file when package.json had no "type": it printed a MODULE_TYPELESS_PACKAGE_JSON warning, "Reparsing as ES module because module syntax was detected", and carried on. Node's documentation says this detection is on by default from v22.7.0 and v20.19.0. With "type": "commonjs" set explicitly, Node.js 25.9.0 failed exactly like Node 18.

The usual fix has a side effect: after adding "type": "module", a CommonJS file in the same package failed with "ReferenceError: require is not defined in ES module scope". Rename such files to .cjs, or convert them.

How to tell this is your problem
WhereWhat you see
node, older versions or "type": "commonjs"SyntaxError: Cannot use import statement outside a module
node 22.7+ / 20.19+, no "type"[MODULE_TYPELESS_PACKAGE_JSON] Warning: … Reparsing as ES module because module syntax was detected

How to know it is actually fixed

  • The file runs under node, with no MODULE_TYPELESS_PACKAGE_JSON warning once the type is set.

Stopping it happening again

  • Set "type" explicitly in every package.json, so the module system never depends on detection.
  • Use .cjs and .mjs for files that must stay in the other system.

Sources

Behaviour described here is drawn from official documentation. Where a figure could not be confirmed on an official page it is attributed in the text rather than stated as canonical.

Did this get you to an answer?

No text box on purpose — please do not paste production logs anywhere

Something wrong or out of date? Report it