How to Fix the ReferenceError “__dirname is Not Defined” in Node.js ES Modules

Written by myTechMarvel | Published 2025/09/09
Tech Story Tags: nodejs | node.js-module-systems | node.js-__dirname-error | __dirname-not-defined-fix | process.cwd-node.js | es-modules | __filename-es-modules | node.js-referenceerror

TLDRIn CommonJS, `__dirname` and `__filename` are built-in globals that give you the current file’s directory and path. ES Modules don’t provide these by default, leading to confusion for many developers migrating their projects or using modern import syntax. In this article, we’ll break down why this error occurs, how ES Module differ from CommonJS and the best practices to fix or work around the issue.via the TL;DR App

When working with Node.js, you might encounter the error: ReferenceError: __dirname is not defined in ES module scope.This usually happens when you switch from CommonJS (require) to ES Modules (import/export). In CommonJS, __dirname and __filename are built-in globals that give you the current file’s directory and path. However, ES Modules don’t provide these by default, leading to confusion for many developers migrating their projects or using modern import syntax.

In this article, we’ll break down why this error occurs, how ES Modules differ from CommonJS, and the best practices to fix or work around the issue in Node.js.

Fix ReferenceError: __dirname is Not Defined in ES Module Scope

CommonJS vs ES Modules in Node.js

When working with Node.js, you’ll often come across two different module systems: CommonJS (CJS) and ECMAScript Modules (ESM). Understanding their differences is key to knowing why __dirname behaves differently.

CommonJS (CJS)

  • Default module system in Node.js until recently.
  • Uses the require() function to import modules.
  • Automatically provides special variables like __dirname and __filename.

Example:

// CommonJS example
const path = require('path');

console.log(__dirname); // absolute path of the current file’s directory
console.log(__filename); // absolute path of the current file

Here, __dirname always works out of the box because CommonJS injects it into every module.

ES Modules (ESM)

  • The standardized JavaScript module system, using import and export.
  • Works in both browsers and Node.js.
  • Does not provide __dirname or __filename by default.

Example:

// ES Module example
import path from 'path';
console.log(__dirname); // ❌ ReferenceError: __dirname is not defined

Since ES Modules are designed to be universal (usable outside of Node.js), Node.js does not include Node-specific globals like __dirname. Instead, you need to rely on import.meta.url and helper functions from the url and path modules to reconstruct similar behavior.

Why ReferenceError: __dirname is Not Defined in ES Module Scope

If you’ve switched from CommonJS to ES Modules, the sudden absence of __dirname can feel confusing. The reason lies in the design philosophy behind ESM.

1. Standardization Across Environments

  • CommonJS was created specifically for Node.js. That’s why it includes Node-specific globals like __dirname and __filename.
  • ES Modules, on the other hand, were designed as a standard JavaScript module system that works in both browsers and Node.js.
  • Since browsers don’t have concepts like file system paths, Node.js doesn’t inject __dirname into ES Modules – otherwise the behavior would diverge from the standard.

2. Different Loading Mechanism

  • CommonJS modules are loaded and wrapped by Node.js, which is why variables like __dirname can be automatically provided.
  • ES Modules are evaluated in a different way. Each file is treated as an independent module, and Node.js doesn’t wrap them with extra variables.
  • Instead of giving you globals, ES Modules encourage explicit imports and usage of built-in tools like import.meta.url.

3. Encouraging Explicit Path Handling

  • With ESM, Node.js pushes developers to be clear and intentional about paths.

Rather than relying on injected globals, you construct the path using:

import { dirname } from 'path';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
  • This makes the code more transparent and portable across different environments.

How to Fix: ReferenceError: __dirname is Not Defined in ES Module Scope

Now that we understand why __dirname isn’t available in ES Modules, let’s look at the most common ways to fix it. Depending on your use case, you can choose one of the following solutions:

Solution 1: Use import.meta.url + fileURLToPath (Recommended)

The modern and most reliable approach is to reconstruct __filename and __dirname using import.meta.url.

// ES Module example
import { fileURLToPath } from 'url';
import { dirname } from 'path';

// Recreate CommonJS globals
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
console.log(__dirname); // Prints current file’s directory
console.log(__filename); // Prints current file path

This method works consistently across Node.js projects using ES Modules and is the closest equivalent to the old CommonJS globals.

Solution 2: Use process.cwd() (Project Root Directory)

If you don’t specifically need the current file’s directory and instead want to work relative to the project root, you can use process.cwd().

console.log(process.cwd()); // Prints the working directory where Node.js was started

This is useful for reading configuration files, logs, or assets located at the root of your project. However, keep in mind that if you run your script from a different folder, the result may change.

Solution 3: Stick with CommonJS

If migrating to ES Modules isn’t required for your project, you can simply keep using CommonJS and continue relying on __dirname as before.

Two ways to do this:

1. Rename your file from .js to .cjs.

Or set your package.json type to CommonJS:

{"type": "commonjs"}

2. Then, your old code will continue working:

const path = require('path');
console.log(__dirname);

Summary of Fixes:

  • For modern ESM projects → use import.meta.url + fileURLToPath.
  • For project-root paths → use process.cwd().
  • For legacy projects → stay with CommonJS.

Best Practices

Now that you know the different fixes, it’s important to choose the right one depending on your project needs. Here are some best practices to follow:

1. Prefer import.meta.url for File-Specific Paths

  • If your code needs the exact file path or directory (like serving static files, saving uploads, or working with relative imports), always use the import.meta.url + fileURLToPath solution.
  • It’s the most future-proof and aligns with ES Module standards.

2. Use process.cwd() for Project-Wide Paths

  • If you only need paths relative to the project root, process.cwd() is simpler and cleaner.
  • Good for configuration files, logs, or assets placed in the root directory.
  • Be careful: the result depends on where you run the node command from.

3. Be Consistent Across Your Project

  • Avoid mixing CommonJS and ES Modules unless you have a strong reason.
  • Choose one module system for your project and stick to it to reduce confusion.

4. Only Use CommonJS if Legacy Support is Required

  • If you’re working on an older project that already relies heavily on CommonJS, it may be easier to stick with it.
  • For new projects, always prefer ES Modules, since they’re the future of JavaScript.

In short:

  • Use import.meta.url for per-file path handling.
  • Use process.cwd() for project-root paths.
  • Stick to one system consistently.
  • Avoid falling back to CommonJS unless absolutely necessary.

Conclusion:  on ReferenceError: __dirname is not defined in ES module scope

The error

ReferenceError: __dirname is not defined in ES module scope

isn’t a bug – it’s a design choice. ES Modules were built to be standard across environments, which means Node.js doesn’t inject Node-specific globals like __dirname.

The good news is that the fix is straightforward:

  • Use import.meta.url with fileURLToPath when you need file-specific paths.
  • Use process.cwd() when you only care about the project root.
  • Or, stick with CommonJS if you’re maintaining older code.

By understanding the difference between CommonJS and ES Modules, and applying the right solution for your case, you can handle file paths in Node.js confidently – without running into unexpected errors.


Written by myTechMarvel | My name is Ankit. I am MEAN Stack Developer.
Published by HackerNoon on 2025/09/09