Fixing 'ReferenceError: __dirname is not defined' in Node.js ES Modules

beginner๐Ÿ’š Node.js2026-05-19| Node.js (v14.13.0+, v16.x, v18.x, v20.x+), macOS, Linux, Windows

Error Message

ReferenceError: __dirname is not defined in ES module scope
#nodejs#esm#javascript#__dirname#backend

Why did __dirname disappear?If you've recently swapped require for import in your Node.js project, you likely hit a wall. You try to access the current directory, and Node.js throws a ReferenceError. This happens because ES Modules (ESM) don't include global variables like __dirname or __filename by default.

CommonJS provides these variables automatically. However, ESM was designed to be platform-agnostic. Since a browser doesn't have a "directory structure" in the same way a server does, these globals were removed to keep ESM consistent across different environments. If you are running Node.js 14 or newer, you'll need to reconstruct these paths manually.

The Solution: Use import.meta.urlTo get your paths back, you need to use import.meta.url. This property gives you the full URL of the current module, such as file:///Users/dev/project/index.js. We can then convert this URL into a standard file path using Node's built-in utilities.

1. Import the path and url modulesStart by bringing in the tools needed to handle file URLs and path strings. Add these lines to the top of your script:

import { fileURLToPath } from 'url';
import { dirname } from 'path';

2. Recreate the missing globalsYou can define __filename and __dirname manually with just two lines of code. This makes your ESM code feel familiar again.

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

3. Putting it all togetherHere is how a typical setup looks when you need to locate a config folder relative to your script:

import path from 'path';
import { fileURLToPath } from 'url';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

// Example: Joining paths for a settings file
const configPath = path.join(__dirname, 'config', 'settings.json');
console.log(`Target path: ${configPath}`);

Testing the FixVerify the solution by creating a file named app.mjs (or app.js if your package.json has "type": "module"). Paste the logic above and run it:

node app.mjs

Your terminal should now print the absolute path to your file and folder. No more ReferenceErrors.

Pro-Tips for ESM File Paths### Don't rely solely on process.cwd()It is tempting to use process.cwd() as a shortcut. Be careful: process.cwd() returns the directory where you started the terminal command, not where the script lives. If you run node ./src/app.js from the root folder, process.cwd() and __dirname will point to different places.

Loading JSON files safelyMost developers need __dirname to read JSON files. While modern Node.js versions (v20.10+) support Import Attributes for JSON, the fs module combined with our __dirname fix remains the most compatible method for older LTS versions:

import { readFileSync } from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';

const __dirname = path.dirname(fileURLToPath(import.meta.url));
const rawData = readFileSync(path.join(__dirname, 'data.json'), 'utf8');
const data = JSON.parse(rawData);

Centralize your path logicIf your project has dozens of files, repeating these lines is tedious. You can't simply export __dirname from a utility file because import.meta.url changes based on the file it is called in. Instead, export a helper function that accepts import.meta.url as an argument to keep your code clean.

Related Error Notes