Quick Solutions
If you need to fix this error immediately, use one of these two industry-standard methods:
- The Project-Wide Fix: Open
package.jsonand add"type": "module"to the root object. - The Single-File Fix: Change your file extension from
.jsto.mjs.
// your package.json should look like this:
{
"name": "my-node-app",
"version": "1.0.0",
"type": "module",
"dependencies": { ... }
}
The Root Cause
Node.js was built in 2009 using CommonJS, a module system that uses require(). Modern JavaScript now uses ECMAScript Modules (ESM), which relies on import and export. These two systems handle variables and loading differently.
By default, Node.js treats every .js file as a CommonJS module. When the engine encounters an import statement in a file it expects to be CommonJS, it stops execution and throws this error:
SyntaxError: Cannot use import statement outside a module
To use modern syntax, you must explicitly signal to Node.js that your environment supports ES Modules.
Method 1: The package.json Approach (Recommended)
This is the most efficient way to manage modern Node.js projects. Setting the type field ensures that every .js file in your directory—and all its subdirectories—is treated as an ES Module.
- Find the
package.jsonfile in your project root. - Insert
"type": "module"into the main configuration block. - Restart your application by running
node app.js.
One important note: This change disables require(). If you try to use const fs = require('fs') in a module, Node will throw an error. You must convert those lines to import fs from 'fs' or rename specific legacy files to .cjs.
Method 2: Using the .mjs Extension
Sometimes you don't want to change the configuration for an entire project. In these cases, the .mjs extension is your best friend. Node.js always treats .mjs files as ES Modules, regardless of what your package.json says.
- Rename
server.jstoserver.mjs. - Execute the file using
node server.mjs.
This approach works well for small scripts or when you are gradually migrating a large codebase to modern JavaScript.
Method 3: Transpiling with TypeScript
If you are using TypeScript, you might encounter this error if your configuration targets an older version of Node. Your tsconfig.json acts as a bridge, converting your import statements into require calls that older Node versions understand.
// tsconfig.json
{
"compilerOptions": {
"module": "CommonJS",
"target": "ES2020",
"esModuleInterop": true
}
}
Using ts-node or tsx to run your files handles this conversion in memory, preventing the SyntaxError during development.
Testing the Fix
Verify your setup by creating a file named check-version.js with the following code:
// check-version.js
import { versions } from 'process';
console.log("Node.js Engine Version:", versions.node);
If you enabled "type": "module", run node check-version.js. If it logs your version (e.g., 20.10.0) without crashing, your environment is correctly configured.
Common Hurdles
- Node.js Versioning: ESM became stable in Node.js v12.17.0. If you are stuck on an older version like v10, you must upgrade to use
importwithout experimental flags. - Explicit Extensions: Unlike CommonJS, ESM requires full file extensions. You cannot write
import { auth } from './auth'; you must writeimport { auth } from './auth.js'. - Directory Imports: Importing a folder to automatically load
index.jsno longer works in ESM. You must point directly to the file path.
Resources
- Official Node.js ESM Documentation
- Guide to CommonJS Compatibility

