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.
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.
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.
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.
Error: Listener already called (once event already fired)
EventEmitter listener already called with once()
Error: EACCES: permission denied, open '/root/file.txt'
EACCES: permission denied
Error: Invalid encoding specified (stream encoding not supported)
How to fix Invalid encoding error in Node.js readable streams
Error: EINVAL: invalid argument, open
EINVAL: invalid argument, open
TypeError: readableLength must be a positive integer (stream config)
TypeError: readableLength must be a positive integer in Node.js streams