Skip to content
Latchkey

Node "__filename is not defined in ES module scope" in CI

Code referenced __filename, a CommonJS-only global, while running as an ES module. ESM has no __filename; you must derive it from import.meta.url.

What this error means

The program crashes at runtime in CI with "ReferenceError: __filename is not defined in ES module scope". The file (or its bundle) is ESM, but the code or a dependency expects CJS globals.

node
ReferenceError: __filename is not defined in ES module scope
    at file:///work/repo/dist/index.js:5:13

Common causes

CJS globals used in ESM code

__filename and __dirname are injected by the CommonJS wrapper. ES modules do not have them.

A CJS dependency bundled into ESM output

esbuild produced an esm bundle but a bundled dependency relies on __filename, which is now undefined.

How to fix it

Derive __filename from import.meta.url

Reconstruct the CJS path globals at the top of the ESM module.

source
import { fileURLToPath } from 'node:url';
import { dirname } from 'node:path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

Inject a banner when bundling to ESM

If a bundled dependency needs the globals, define them via an esbuild banner.

build script
esbuild.build({
  format: 'esm',
  banner: { js: "import{fileURLToPath}from'url';import{dirname}from'path';const __filename=fileURLToPath(import.meta.url);const __dirname=dirname(__filename);" },
});

How to prevent it

  • Use import.meta.url-derived paths in ESM code.
  • Inject __filename/__dirname banners when bundling CJS deps to ESM.
  • Run the built ESM artifact in CI to catch missing globals.

Related guides

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