The error, verbatim
Jump to the fix ↓ReferenceError: __dirname is not defined in ES module scope
ReferenceError: require is not defined in ES module scope, you can use import instead
This file is being treated as an ES module because it has a '.js' file
extension and 'package.json' contains "type": "module".
Tested on
- Node
- 24.14.0 and 26.11.1; re-run on 20.20.2, 22.23.4, 24.22.1 and 26.13.0 (Linux)
- Module type
- "type": "module" and .mjs
- OS
- Windows 11 Pro
✓ Last re-run on GitHub Actions · see the run · all repros
Contents
require, __dirname and __filename aren’t real globals. Node adds them to every CommonJS file, and ES modules don’t get them. So the moment Node treats your file as an ES module, all three are gone, with one of these errors:
ReferenceError: require is not defined in ES module scope, you can use import instead
ReferenceError: __dirname is not defined in ES module scope
ReferenceError: __filename is not defined in ES module scope
Node runs a file as an ES module in two cases, and the second line of its message says which one applies to you:
- the file ends in
.jsand the nearestpackage.jsonhas"type": "module" - the file ends in
.mjs, whateverpackage.jsonsays
This file is being treated as an ES module because it has a '.js' file extension and 'D:\project\package.json' contains "type": "module". To treat it as a CommonJS script, rename it to use the '.cjs' file extension.
On October 31, 2026 I re-ran all three on Node 24.14.0 and 26.11.1: the same errors on both. Node 26 prints the package.json path with a \\?\ prefix on Windows ('\\?\D:\project\package.json'), but the meaning is the same.
The usual way into this is copying CommonJS code into a project that was set up as ES modules (most new templates are), or adding "type": "module" to an older project.
__dirname and __filename
Use import.meta.dirname and import.meta.filename. They’re built into Node and need no imports:
import path from "node:path";
const dataFile = path.join(import.meta.dirname, "data.json");
console.log(import.meta.dirname); // folder of this file
console.log(import.meta.filename); // full path of this fileimport.meta.dirname and import.meta.filename were added in Node 20.11. On an older Node, use the classic two-line fallback:
import path from "node:path";
import { fileURLToPath } from "node:url";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);require
1. Use import (the normal fix in an ES module project):
import isNumber from 'is-number';2. Keep require with createRequire, for code you can’t easily change:
import { createRequire } from 'node:module';
const require = createRequire(import.meta.url);
const isNumber = require('is-number');3. Make that one file CommonJS by renaming it to .cjs. It can then use require, __dirname and __filename, while the rest of the project stays ES modules.
require() of a JSON file
const data = require('./data.json') is a common reason to reach for require. A plain import doesn’t work for JSON:
TypeError [ERR_IMPORT_ATTRIBUTE_MISSING]: Module "file:///D:/project/data.json" needs an import attribute of "type: json"
Add the import attribute:
import data from './data.json' with { type: 'json' };Leave the with part out and the import fails before your code runs: TypeError [ERR_IMPORT_ATTRIBUTE_MISSING]: Module "…/data.json" needs an import attribute of "type: json" on Node 22, 24 and 26, and ERR_IMPORT_ASSERTION_TYPE_MISSING on Node 20.
What didn’t work
Versions I checked
A folder with "type": "module" in its package.json, one file per case (require, __dirname, __filename), a data.json, a file using every fix above, and a .cjs file, run with Node 24.14.0 and Node 26.11.1 on Windows 11 Pro on October 31, 2026. The original tests were on Node 24.14.0 in September and October. Error text is copied from the runs; only the project path is shortened.
November 3, 2026: every case ran on Node 20.20.2, 22.23.4, 24.22.1 and 26.13.0 on Linux (GitHub Actions ubuntu-latest). The three ReferenceError messages were word for word the same on all four, .mjs still failed the same way, and import.meta.dirname / import.meta.filename, the fileURLToPath fallback, import, createRequire, a .cjs file and the JSON import with with { type: 'json' } all worked on every version. The script and the run are public.
— N.K., end of entry No.002