Node "__dirname is not defined in ES module scope" in CI
CommonJS injects __dirname and __filename into every module, but ES modules do not have them. In ESM you derive the directory from import.meta.url instead.
What this error means
Code that builds a path from __dirname fails under ESM with "ReferenceError: __dirname is not defined in ES module scope".
node
const config = path.join(__dirname, 'config.json');
^
ReferenceError: __dirname is not defined in ES module scopeCommon causes
CommonJS path globals used in an ESM file
__dirname/__filename are CommonJS module wrappers; they are not provided in ES module scope.
Code moved to ESM without porting path logic
A file converted to "type": "module" still references the old globals to resolve relative paths.
How to fix it
Derive __dirname from import.meta.url
Use fileURLToPath to convert the module URL into a filesystem path.
index.js
import { fileURLToPath } from 'node:url';
import path from 'node:path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);Use import.meta.dirname on newer Node
Node 20.11+ and 21.2+ expose import.meta.dirname and import.meta.filename directly.
index.js
const config = path.join(import.meta.dirname, 'config.json');How to prevent it
- Prefer
import.meta.dirnamewhen your minimum Node supports it. - Resolve assets relative to
import.meta.url, not assumed CWD. - Audit for
__dirname/__filenamewhen converting a package to ESM.
Related guides
Node "ReferenceError: require is not defined in ES module scope" in CIFix Node "ReferenceError: require is not defined in ES module scope" in CI - the file runs as an ES module wh…
Node "SyntaxError: Cannot use import statement outside a module" in CIFix Node "SyntaxError: Cannot use import statement outside a module" in CI - the file used ESM import syntax…
Node "SyntaxError: top-level await is only available in ES modules" in CIFix Node "SyntaxError: Unexpected reserved word" / "top-level await is only available in ES modules" in CI -…