How to Resolve the "ReferenceError: __dirname is not defined in ES module scope" Error in JavaScript
When migrating a Node.js project from the traditional CommonJS module system to the modern ECMAScript Modules (ESM) standard, a common error you will encounter is ReferenceError: __dirname is not defined in ES module scope. This happens because the classic __dirname and __filename global variables are not available in ES modules.
This guide will explain why these variables don't exist in ESM and teach you the modern, standard method for getting the current module's directory and file path using the import.meta.url object.
The Core Problem: Why __dirname and __filename Don't Exist in ESM
In the CommonJS module system, __dirname and __filename are special variables that Node.js injects into each module. They provide the absolute path to the current module's directory and file, respectively.
ECMAScript Modules, however, are a standardized part of the JavaScript language and are not specific to Node.js. They are designed to work in different environments (like browsers), where the concept of a file system path doesn't always exist. To provide module-specific information in a standardized way, ESM introduces the import.meta object.
The Modern Solution: Using import.meta.url
The standard and correct way to get the current module's path in an ES module is to use a combination of the built-in url and path modules.
For example, in an ES module, this code will throw an error.
// Problem: This code runs in an ES module (e.g., with "type": "module" in package.json).
// ⛔️ ReferenceError: __dirname is not defined
console.log(__dirname);
This is the standard pattern to replicate the functionality of __dirname and __filename.
// You must import these built-in Node.js modules.
import path from 'path';
import { fileURLToPath } from 'url';
// Get the full path to the current file.
const __filename = fileURLToPath(import.meta.url);
// Get the directory name of the current file.
const __dirname = path.dirname(__filename);
// Now you can use them just like in CommonJS.
console.log('Current file path:', __filename);
console.log('Current directory path:', __dirname);
// Example: Construct a path to a file in the same directory
const filePath = path.join(__dirname, 'data.json');
console.log('Path to data.json:', filePath);
How the Solution Works
import.meta.url: This is the starting point. It's a special property available only in ES modules that provides the URL of the current module. This URL will be in afile://format.// Example output of import.meta.url
'file:///C:/Users/YourUser/Desktop/MyProject/index.js'fileURLToPath(): This helper function from theurlmodule takes thefile://URL and correctly converts it into a platform-specific, absolute file path that Node.js can work with.// Example output of __filename
'C:\\Users\\YourUser\\Desktop\\MyProject\\index.js'path.dirname(): This standard function from thepathmodule takes a file path and returns its parent directory, effectively giving you the value that__dirnameused to provide.// Example output of __dirname
'C:\\Users\\YourUser\\Desktop\\MyProject'
Creating Reusable Helper Functions (Best Practice)
If you need to access __dirname or __filename in multiple files, it's a good practice to create a small utility file to avoid repeating this logic.
import path from 'path';
import { fileURLToPath } from 'url';
export function getDirname(metaUrl) {
const __filename = fileURLToPath(metaUrl);
return path.dirname(__filename);
}
import { getDirname } from './utils.js';
const __dirname = getDirname(import.meta.url);
console.log(`The current directory is: ${__dirname}`);
Conclusion
The __dirname is not defined error is a standard part of the transition from CommonJS to ES Modules in Node.js.
- The root cause is that the
__dirnameand__filenameglobals do not exist in ES modules. - The correct, modern solution is to use the
import.meta.urlobject. - You must then use the
fileURLToPath()andpath.dirname()helper functions to convert this URL into the familiar directory and file paths.
By adopting this modern pattern, you can write ES modules that are fully aware of their location on the file system.