This error occurs when attempting to use __dirname or __filename in ES modules. These CommonJS globals are not available in ES module scope, requiring alternative approaches using import.meta.url or the newer import.meta.dirname.
The "__dirname is not defined" error occurs because __dirname and __filename are CommonJS-specific globals that are not included in the ECMAScript module specification. When you use ES modules (identified by "type": "module" in package.json or .mjs file extensions), Node.js does not automatically provide these variables. This design decision was intentional. ES modules were created to work in both browser and server environments. Since browsers don't have file system access, providing directory path globals wouldn't make sense in that context. To maintain consistency across environments, the ES module specification omitted these Node.js-specific variables. Instead, ES modules provide import.meta.url, which contains the file URL of the current module. This can be converted to a file path and directory path using Node.js utilities, or in modern Node.js versions (20.11.0+), you can use the built-in import.meta.dirname and import.meta.filename properties directly.
If you're using Node.js version 20.11.0 or newer, you can use the built-in import.meta.dirname and import.meta.filename properties:
// Get the directory name (replaces __dirname)
console.log(import.meta.dirname);
// Output: /home/user/project/src
// Get the file name (replaces __filename)
console.log(import.meta.filename);
// Output: /home/user/project/src/index.js
// Use in path operations
import { join } from 'path';
const configPath = join(import.meta.dirname, 'config.json');Check your Node.js version with node --version. This is the cleanest and most modern solution requiring no imports or utility functions.
For Node.js versions before 20.11.0, manually recreate __dirname and __filename using the url and path modules:
import { fileURLToPath } from 'url';
import { dirname } from 'path';
// Convert import.meta.url to a file path
const __filename = fileURLToPath(import.meta.url);
// Get the directory name
const __dirname = dirname(__filename);
console.log(__dirname); // /home/user/project/src
console.log(__filename); // /home/user/project/src/index.jsPlace this code at the top of any module where you need __dirname. You can also create a utility file that exports these values if you need them in multiple modules.
If you frequently need to resolve paths relative to module files, create a utility function:
// utils/paths.js
import { fileURLToPath } from 'url';
import { dirname, join } from 'path';
export function getDirname(importMetaUrl) {
const __filename = fileURLToPath(importMetaUrl);
return dirname(__filename);
}
export function resolveFromModule(importMetaUrl, ...paths) {
const dir = getDirname(importMetaUrl);
return join(dir, ...paths);
}Then use it in your modules:
// src/index.js
import { resolveFromModule } from './utils/paths.js';
const configPath = resolveFromModule(import.meta.url, '../config/app.json');
const dataPath = resolveFromModule(import.meta.url, 'data', 'users.db');If you're not ready to use ES modules or encounter compatibility issues, revert to CommonJS. Remove or change "type": "module" in package.json:
{
"type": "commonjs"
}Or simply omit the "type" field (CommonJS is the default). Then change your imports to requires:
// ES module syntax
import fs from 'fs';
import path from 'path';
// CommonJS syntax
const fs = require('fs');
const path = require('path');Rename .mjs files to .js if applicable. With CommonJS, __dirname and __filename will work normally. However, note that ES modules are the future standard and offer better tree-shaking and static analysis benefits.
TypeScript configuration: When using TypeScript with ES modules, ensure your tsconfig.json has "module": "ESNext" or "module": "ES2022" and "moduleResolution": "node16" or "bundler". If you target older Node.js versions, you'll need to include the fileURLToPath workaround in your source code before compilation.
URL vs file paths: import.meta.url returns a file:// URL (like file:///home/user/project/file.js), not a file path. Always use fileURLToPath() to convert it before passing to file system operations or path utilities. Directly using the URL string can cause issues on Windows.
Directory detection alternative: You can get the directory path directly without creating __filename first:
import { fileURLToPath } from 'url';
const __dirname = fileURLToPath(new URL('.', import.meta.url));The '.' in new URL('.', import.meta.url) resolves to the directory containing the current module.
Bundler considerations: If you're using bundlers like webpack, esbuild, or Rollup, they may handle import.meta.url differently or provide their own globals. Check your bundler's documentation for the recommended approach.
Mixed CommonJS/ESM projects: In projects using both module systems, consider creating wrapper utilities that detect the module type and provide unified path resolution. Some packages like node:path work identically in both contexts, but global availability differs.
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