This error occurs when attempting to use CommonJS require() syntax in code being treated as an ES module. Node.js uses different module systems, and require() is not available in ES module scope.
This error indicates that your code is attempting to use the CommonJS `require()` function, but Node.js is treating your file as an ES module where `require()` is not defined. This typically happens when your package.json includes `"type": "module"`, your file has a `.mjs` extension, or you're using ES module syntax elsewhere in the project. ES modules (ESM) and CommonJS are two different module systems in Node.js. CommonJS uses `require()` and `module.exports`, while ES modules use `import` and `export` statements. When Node.js treats a file as an ES module, it doesn't provide the CommonJS globals like `require`, `__dirname`, or `__filename`. The error message often includes "you can use import instead" as a hint to migrate to ES module syntax. This is part of Node.js's gradual transition toward ES modules as the standard module system.
First, verify if your project is configured to use ES modules:
cat package.json | grep '"type"'If you see "type": "module", this means all .js files are treated as ES modules. You have two options: remove this setting to use CommonJS, or convert your code to use ES module syntax.
The most straightforward solution is to use ES module syntax. Replace require() calls with import statements:
Before (CommonJS):
const fs = require('fs');
const express = require('express');
const myModule = require('./myModule');After (ES Module):
import fs from 'fs';
import express from 'express';
import myModule from './myModule.js';Note: ES modules require file extensions in relative imports (./myModule.js not ./myModule).
If you need to use require() in an ES module (for example, to load JSON files or CommonJS-only packages), create a require function:
import { createRequire } from 'module';
const require = createRequire(import.meta.url);
// Now you can use require()
const data = require('./config.json');
const oldModule = require('legacy-commonjs-package');This approach allows you to maintain ES module syntax while still accessing CommonJS modules when needed.
If you prefer to use CommonJS throughout your project, remove the ES module configuration:
Edit package.json:
{
"name": "your-project",
"version": "1.0.0",
// Remove this line:
// "type": "module"
}After removing this, all .js files will be treated as CommonJS modules, and require() will work normally.
You can be explicit about which module system each file uses by renaming:
For CommonJS modules:
mv script.js script.cjsFor ES modules:
mv script.js script.mjsFiles with .cjs extensions are always treated as CommonJS (can use require()), and files with .mjs extensions are always treated as ES modules (must use import), regardless of package.json settings.
If you're using other CommonJS globals like __dirname or __filename, replace them with ES module equivalents:
Before (CommonJS):
const path = require('path');
const configPath = path.join(__dirname, 'config.json');After (ES Module):
import { fileURLToPath } from 'url';
import { dirname, join } from 'path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const configPath = join(__dirname, 'config.json');Or in Node.js 20.11.0+, use the new built-in properties:
import { join } from 'path';
const configPath = join(import.meta.dirname, 'config.json');Module System Detection: Node.js determines whether a file is CommonJS or ES module based on: (1) file extension (.mjs = ESM, .cjs = CommonJS, .js = depends on package.json), (2) nearest package.json's "type" field ("module" = ESM, "commonjs" or absent = CommonJS), (3) --input-type flag for stdin input.
Mixed Module Systems: You can use both module systems in the same project by being explicit with file extensions. Use .cjs for CommonJS files and .mjs for ES module files. This overrides the package.json "type" setting for specific files.
JSON Imports in ES Modules: To import JSON files in ES modules, use import assertions (experimental in older Node versions, stable in Node.js 17.5+):
import data from './config.json' assert { type: 'json' };Or use createRequire() as shown in the steps above.
Dynamic Imports: ES modules support dynamic imports which return promises and work in both CommonJS and ES modules:
const module = await import('./myModule.js');Top-Level Await: ES modules support top-level await, allowing you to use await outside of async functions. This is not available in CommonJS.
Build Tool Considerations: If using bundlers like webpack, Rollup, or esbuild, they may have their own module resolution logic. Check your bundler configuration if this error appears during builds rather than runtime.
Serverless Environments: AWS Lambda and other serverless platforms support both module systems. If deploying Lambda functions with ES modules, ensure your package.json includes "type": "module" and use .mjs extensions or import syntax consistently.
TypeScript Projects: When using TypeScript, set "module": "ESNext" or "module": "ES2020" in tsconfig.json to generate ES module output. If targeting CommonJS, use "module": "CommonJS".
Performance: ES modules are parsed before execution, enabling better optimization and tree-shaking. CommonJS modules are executed during loading, which can impact startup time but allows for conditional requires.
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