This error occurs when trying to use the CommonJS global __filename in an ES module. ES modules use a different approach to access file paths and do not provide __filename by default.
The __filename global variable is a CommonJS feature that provides the absolute path of the currently executing file. When Node.js runs in ES module mode (either through "type": "module" in package.json or using .mjs file extensions), these CommonJS globals are not available. This is by design - ES modules follow the ECMAScript specification which doesn't include these Node.js-specific globals, aiming for better compatibility with browser environments and standardized JavaScript. The error occurs when your code attempts to reference __filename in an ES module context.
Check your package.json for "type": "module" or verify your file has a .mjs extension:
{
"type": "module"
}If you see this, you're in ES module mode and need to use the ES module alternatives.
If you're running Node.js version 20.11.0 or higher, you can use the modern built-in properties:
console.log(import.meta.filename); // Current file path
console.log(import.meta.dirname); // Current directory pathThis is the simplest and recommended approach for modern Node.js versions. Check your version with node --version.
For Node.js versions before 20.11.0, manually create __filename and __dirname using import.meta.url:
import path from 'path';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// Now you can use __filename and __dirname as before
console.log(__filename);
console.log(__dirname);This replicates the CommonJS behavior in ES modules.
If you need __filename/__dirname across many files, create a shared utility:
// utils/paths.js
import path from 'path';
import { fileURLToPath } from 'url';
export function getDirname(importMetaUrl) {
const __filename = fileURLToPath(importMetaUrl);
return path.dirname(__filename);
}
export function getFilename(importMetaUrl) {
return fileURLToPath(importMetaUrl);
}Then use it in your files:
import { getDirname, getFilename } from './utils/paths.js';
const __dirname = getDirname(import.meta.url);
const __filename = getFilename(import.meta.url);If you don't need ES modules, you can switch back to CommonJS:
1. Remove "type": "module" from package.json
2. Rename .mjs files to .js (or use .cjs extension)
3. Replace import/export with require()/module.exports
// CommonJS style
const path = require('path');
console.log(__filename); // Works in CommonJS
console.log(__dirname);Only choose this if you have a specific reason to avoid ES modules.
Understanding import.meta
The import.meta object is part of the ES module specification and provides metadata about the current module. In Node.js, it includes:
- import.meta.url: File URL of the current module (e.g., "file:///path/to/file.js")
- import.meta.filename: Absolute file path (Node.js 20.11.0+)
- import.meta.dirname: Directory path (Node.js 20.11.0+)
Browser Compatibility Note
The import.meta.filename and import.meta.dirname properties only work when the URL scheme is "file:", so they're not available in browser environments. If you're writing code that runs in both Node.js and browsers, avoid using these properties or provide browser-compatible alternatives.
TypeScript Considerations
If using TypeScript with ES modules, ensure your tsconfig.json has:
{
"compilerOptions": {
"module": "ESNext",
"moduleResolution": "node"
}
}TypeScript will properly recognize import.meta properties when configured for ES modules.
Related CommonJS Globals
Other CommonJS globals not available in ES modules include:
- __dirname: Use the same solutions as __filename
- require: Use dynamic import() instead
- require.resolve: Use import.meta.resolve() (Node.js 20.6.0+)
- module, exports: Use ES module export syntax
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