Skip to content
Latchkey

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 scope

Common 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.dirname when your minimum Node supports it.
  • Resolve assets relative to import.meta.url, not assumed CWD.
  • Audit for __dirname/__filename when converting a package to ESM.

Related guides

Tired of flaky CI? Latchkey auto-heals failed jobs and retries them for you. Start free →