How to fix SyntaxError: Cannot use import statement outside a module in Node.js
This error occurs when Node.js encounters ES6 import syntax in a file that is being treated as a CommonJS module. Node.js defaults to CommonJS and requires explicit configuration to use ES modules with import/export syntax.
Quick fix
Fixes ERR_REQUIRE_ESM
{
"name": "your-project",
"version": "1.0.0",
"type": "module",
"scripts": {
"start": "node index.js"
}
}- Add "type": "module" to package.json
- Use .mjs file extension for ES modules
- Convert ES module syntax to CommonJS
- Update Node.js version if needed
{"name": "your-project","version": "1.0.0","type": "module","scripts": {"start": "node index.js"}}SyntaxError: Cannot use import statement outside a module
What this error means
This error indicates that Node.js has encountered an `import` statement in a JavaScript file that it is interpreting as a CommonJS module rather than an ES module. Historically, Node.js used CommonJS as its module system, where modules are loaded using `require()` and exported with `module.exports`. ES modules (ESM), which use `import` and `export` statements, are a newer standard that Node.js has supported since version 12. Node.js determines whether to treat a file as CommonJS or ESM based on several factors: the file extension (.js, .mjs, or .cjs), the "type" field in the nearest package.json file, and command-line flags. By default, .js files are treated as CommonJS modules. When Node.js tries to execute a .js file containing `import` statements without being configured to recognize it as an ES module, it throws this syntax error. The error is particularly common when developers are migrating from CommonJS to ES modules, working with modern JavaScript frameworks, or when dependencies have been updated to use ES module syntax. It's a configuration issue rather than a code error—your import statements are valid ES module syntax, but Node.js needs to be told to interpret them as such.
Typical symptoms
- Application crashes immediately at startup with SyntaxError
- Error message mentions "Cannot use import statement outside a module"
- Code with import/export statements fails to run despite being valid JavaScript
- Tests fail with module-related syntax errors
- Scripts that previously worked stop functioning after Node.js upgrade
Common causes
- No "type": "module" field in package.json while using .js file extension
- Using .js extension instead of .mjs for ES module files
- Mixing CommonJS and ES module syntax without proper configuration
- Node.js version older than 12 (limited or no ES module support)
- Incorrect file extension mapping in test runners like Jest
- Build tools or transpilers not configured to handle ES modules
How to fix "SyntaxError: Cannot use import statement outside a module"
The most common and recommended solution is to add "type": "module" to your package.json file. This tells Node.js to treat all .js files in your project as ES modules:
{
"name": "your-project",
"version": "1.0.0",
"type": "module",
"scripts": {
"start": "node index.js"
}
}After adding this field, restart your application. All .js files will now be interpreted as ES modules, allowing you to use import and export statements freely.
Important: If you have existing CommonJS files that use require(), you'll need to either convert them to ES modules or rename them with a .cjs extension.
If you don't want to change your entire project to ES modules, you can use the .mjs extension for individual files that need ES module syntax:
# Rename your file
mv index.js index.mjsThen run it normally:
node index.mjsNode.js automatically recognizes .mjs files as ES modules, regardless of the package.json "type" field. This approach is useful when you want to gradually migrate to ES modules or maintain a mixed codebase.
Note: When importing local files in .mjs files, you must include the file extension:
// Correct
import { myFunction } from './utils.mjs';
// Incorrect - will fail
import { myFunction } from './utils';If you need to stick with CommonJS (for example, due to compatibility requirements), convert your import statements to require():
Before (ES modules):
import express from 'express';
import { readFile } from 'fs/promises';
export function handler() {
// ...
}After (CommonJS):
const express = require('express');
const { readFile } = require('fs/promises');
function handler() {
// ...
}
module.exports = { handler };This approach works immediately without any configuration changes but means you won't be using modern ES module features.
ES modules require Node.js version 12 or higher (with 13.2+ recommended for stable support). Check your Node.js version:
node --versionIf you're on an older version, update Node.js:
# Using nvm (recommended)
nvm install 20
nvm use 20
# Or download from nodejs.org
# https://nodejs.org/Node.js 20 LTS and above have excellent ES module support and are recommended for new projects.
If you're encountering this error in tests, configure your test runner to handle ES modules. For Jest, create or update jest.config.js:
export default {
testEnvironment: 'node',
transform: {},
extensionsToTreatAsEsm: ['.ts'],
moduleNameMapper: {
'^(\.{1,2}/.*)\.js$': '$1'
}
};You may also need to add --experimental-vm-modules flag:
{
"scripts": {
"test": "NODE_OPTIONS=--experimental-vm-modules jest"
}
}For Vitest (which has better ES module support):
// vitest.config.js
export default {
test: {
environment: 'node'
}
};Consider switching to Vitest if you're starting a new project, as it's designed with ES modules in mind.
Advanced notes
Mixed Module Systems: You can use both CommonJS and ES modules in the same project by being explicit with file extensions. Use .mjs for ES modules, .cjs for CommonJS modules, and set "type": "module" in package.json. Any .js files will follow the "type" field, while .mjs and .cjs files override it.
Importing CommonJS from ES Modules: ES modules can import CommonJS modules using standard import syntax. Node.js automatically converts CommonJS exports to ES module default exports:
// CommonJS file: utils.cjs
module.exports = { foo: 'bar' };
// ES Module file: app.mjs
import utils from './utils.cjs';
console.log(utils.foo); // 'bar'Dynamic Imports in CommonJS: If you need to import ES modules from CommonJS code, use dynamic import(), which is asynchronous:
// In CommonJS file
async function loadModule() {
const module = await import('./esm-module.mjs');
module.doSomething();
}TypeScript Considerations: When using TypeScript, set "module": "ES2020" or higher and "moduleResolution": "node16" or "bundler" in tsconfig.json. TypeScript will emit ES modules that work with Node.js when you compile with tsc.
Package Exports: For library authors, use the "exports" field in package.json to provide both CommonJS and ES module versions of your package, ensuring compatibility with all Node.js projects.
File Extension Requirements: ES modules require explicit file extensions in import statements when importing local files. This is different from CommonJS where extensions are optional. Always include .js, .mjs, or other extensions in your import paths.
Frequently asked questions
- What does "ERR_REQUIRE_ESM" mean?
- js has encountered an import statement in a JavaScript file that it is interpreting as a CommonJS module rather than an ES module. exports. js has supported since version 12.
- How do I fix "ERR_REQUIRE_ESM"?
- This error occurs when Node.js encounters ES6 import syntax in a file that is being treated as a CommonJS module. Node.js defaults to CommonJS and requires explicit configuration to use ES modules with import/export syntax.
- What causes "ERR_REQUIRE_ESM"?
- No "type": "module" field in package.json while using .js file extension Using .js extension instead of .mjs for ES module files Mixing CommonJS and ES module syntax without proper configuration
- Is the "ERR_REQUIRE_ESM" error serious?
- It is a medium-severity error — more of a blocker than a risk. The steps above resolve it.
Official resources & further reading
- 📚Node.js Official Documentation
- 📖Node.js ES modules documentation(Official Docs)
- 📖Node.js packages documentation(Official Docs)
- 📝