TypeScript

Fix ESLint: Module.createRequire is not a function

Reproduced on Node 10 vs Node 18 with the same node_modules: the crash is the Node runtime executing ESLint, not Parcel or a broken module resolution.

Mahdi Ben RhoumaMahdi Ben Rhouma
8 min read

TL;DR#

Module.createRequire is a Node.js API added in v12.2.0. ESLint 7 and 8 call it at startup, inside @eslint/eslintrc, to load the active config file. If the Node binary that actually runs eslint is older than v12.2.0 — commonly because an IDE or a version manager points it at a different interpreter than the one your terminal reports — that method does not exist yet, and ESLint crashes before it lints a single file. The fix is to make the Node that runs ESLint match the version npm install already warned you about, not to touch Parcel, TypeScript, or your .eslintrc.json.

text
Oops! Something went wrong! :(
 
ESLint: 8.7.0
 
TypeError: Module.createRequire is not a function
    at Object.<anonymous> (/app/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2383:26)
    at Module._compile (/app/node_modules/v8-compile-cache/v8-compile-cache.js:192:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:789:10)
    at Module.load (internal/modules/cjs/loader.js:653:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
    at Function.Module._load (internal/modules/cjs/loader.js:585:3)
    at Module.require (internal/modules/cjs/loader.js:692:17)
    at require (/app/node_modules/v8-compile-cache/v8-compile-cache.js:159:20)
    at Object.<anonymous> (/app/node_modules/eslint/lib/cli-engine/cli-engine.js:33:5)

This is the original report on Stack Overflow: "ESLint: Initialization error (ESLint). Module.createRequire is not a function", filed against a React + Parcel + TypeScript project on Node 16.6.2 (as shown by node -v), ESLint 8.7.0, with an airbnb-based .eslintrc.json.

Why the Node interpreter outruns the terminal#

ESLint's own maintainers answered this directly in eslint/eslint#15211, a near-identical crash reported two months before the Stack Overflow question: "eslint v8 requires Node.js >= 12.22.0, please try to upgrade your Node.js." The crashing line lives in @eslint/eslintrc's compiled bundle:

js
const require$1 = Module.createRequire(require('url').pathToFileURL(__filename).toString());

Module.createRequire is a real, current Node.js API — it is not deprecated or renamed. Node's own documentation dates it precisely: "Added in: v12.2.0" for module.createRequire(filename). Below that version the method is simply absent from the module core module, so the Object.<anonymous> call throws a TypeError the instant ESLint's config loader is first required — before any file is linted, which is why the crash reads as an "Initialization error".

ESLint 8.7.0's own package.json states the Node range it needs: ^12.22.0 || ^14.17.0 || >=16.0.0. npm install already warns about it in plain text when the mismatch is present at install time:

text
npm WARN notsup Unsupported engine for eslint@8.7.0: wanted: {"node":"^12.22.0 || ^14.17.0 || >=16.0.0"} (current: {"node":"10.24.1","npm":"6.14.12"})
npm WARN notsup Unsupported engine for @eslint/eslintrc@1.4.1: wanted: {"node":"^12.22.0 || ^14.17.0 || >=16.0.0"} (current: {"node":"10.24.1","npm":"6.14.12"})

But that warning only fires for the Node that ran npm install — not necessarily the Node that later runs eslint. That gap is exactly what makes the Stack Overflow report confusing: the asker's node -v printed 16.6.2, well above the floor, yet ESLint still crashed as if it were running on Node 10. The accepted-style answer with the highest score (60) names the real cause for a WebStorm setup: the IDE had its own "Node interpreter" setting pointing at an old, separately-installed Node (version 10 in that report), independent of the terminal's nvm-selected 16.14.0. One commenter on the GitHub issue reports the same symptom while using fnm and resolving it by switching to nvm — again a case of the tool that launches ESLint resolving a different Node binary than the one node -v reports in a plain shell. Parcel, TypeScript and the specific ESLint config (airbnb, plugin:react/recommended) play no part in the crash itself: this reproduces with a bare eslint --version call and no project files at all.

Reproduced#

With the exact eslint@8.7.0 + @eslint/eslintrc@1.4.1 pair from the question's package.json, installed once with npm install on the official node:18-slim Docker image (which satisfies the engines range), then run unchanged — same node_modules, nothing else touched — under two official Node images:

  • node:18-slim (Node 18.20.8, inside the supported range): eslint --version prints v8.7.0.
  • node:10 (Node 10.24.1, below the v12.2.0 floor): the exact same crash as above, TypeError: Module.createRequire is not a function, at the exact same line of eslintrc.cjs.

One variable changed — the Node binary running the identical node_modules — and the crash appears and disappears with it. That isolates the cause to the runtime, not the dependency tree, Parcel, or the lint config (6 November 2026).

Fix the Node interpreter, not the lint config#

  1. Find out which Node actually runs ESLint, not which Node your shell reports. node -v in a terminal only tells you about that terminal's interpreter. Run the check from the same place ESLint is invoked:

    bash
    node_modules/.bin/eslint --version
    # if that alone throws the TypeError, the problem is confirmed before step 2

    In an IDE, check the editor's own interpreter setting. The top answer names the exact control panel for WebStorm: Ctrl+Alt+S → Languages & Frameworks → Node.js, where Node interpreter can point at a different, older Node install than the one on your PATH.

  2. If you use VS Code, the ESLint extension has the same kind of override. Its own README documents it: "eslint.runtime - use this setting to set the path of the node runtime to run ESLint under." Set it to a Node binary that satisfies ESLint's engines field, or remove the override entirely to fall back to your system Node.

  3. Align the version with what ESLint actually declares, rather than guessing a number:

    bash
    node -p "require('./node_modules/eslint/package.json').engines"
    # {"node":"^12.22.0 || ^14.17.0 || >=16.0.0"}  — for eslint@8.7.0

    Install (or point your editor at) a Node release inside that range — any current LTS satisfies it. If you manage versions with nvm or fnm, run nvm use <version> (or the fnm equivalent) in the same shell, or the same terminal profile, your editor actually launches ESLint from.

  4. Only if you cannot change the Node version at all (a frozen CI image, for example), downgrade ESLint itself to an earlier major release whose startup code does not reach that createRequire call path — a commenter on eslint/eslint#15211 reports an older ESLint 7 release worked around it this way on an old Node. This is a last resort, not the fix — it trades the crash for an unmaintained linter version, and you still have to confirm the exact release against your own project.

Verify the fix#

bash
node_modules/.bin/eslint --version
# v8.7.0   (no TypeError, no stack trace)

This is the same command reproduced above: it prints the version cleanly under Node 18, and throws the Module.createRequire TypeError under Node 10, with the identical node_modules. If that command succeeds but your actual npm run lint script still crashes the same way, check whatever process manager runs that script (husky, a VS Code task, a CI runner) for its own Node selection — the mismatch can live one layer further up than your interactive shell.

One email a month — the latest explained errors

What the site published that month — mostly Next.js, Supabase and Node errors, explained. You confirm by email; unsubscribe any time in one click.

What breaks next, once the runtime is right#

Reinstalling dependencies after fixing the Node version can also change what breaks next. If a typescript-eslint parser error now says a file "was not found by the project service" even though it is covered by your ignores, that is a scoping mistake in .eslintrc/flat config, not a runtime one — see Fix 'was not found by the project service' in ESLint. If instead you now see Parsing error: The keyword 'enum' is reserved, Espree (ESLint's default parser) cannot read a TypeScript enum, and the fix is @typescript-eslint/parser — covered in Fix 'The keyword enum is reserved' in ESLint + TypeScript. And if the next npm install itself fails with an engine warning inside a Docker build rather than your editor, that is the same family of Node-version mismatch, but at the image layer, where a floating global npm upgrade has outgrown the base image's Node — see Fix Docker npm EBADENGINE: Unsupported engine.

A Node version old enough to trigger this crash is also old enough to miss other modern syntax ESLint itself now uses. On the current major release (ESLint 10.14.0, which requires Node ^20.19.0 || ^22.13.0 || >=24), running the same old Node (10) never reaches the Module.createRequire line at all — it fails earlier, with SyntaxError: Unexpected token . on an optional-chaining call (mod.enableCompileCache?.()) in ESLint's own startup script. The specific Module.createRequire message belongs to the ESLint 7/8 era's @eslint/eslintrc + v8-compile-cache bundling, which is still what a large share of 2022-era React/TypeScript/Parcel projects have pinned in their lockfiles — but on any ESLint release, old or current, the underlying fault is the same: the Node binary that launches ESLint is older than the version ESLint's own package.json requires, independent of what your terminal's node -v shows.

Frequently Asked Questions

|

Have more questions? Contact us

Still stuck? Paste your error.

Paste the error message or stack trace — we check it against every fix and tool on the site.

Matching happens in your browser. When you search, a cleaned error signature is sent so we can spot errors we do not cover yet — never the raw text, your IP address or your e-mail. Do not paste passwords or keys. Details

Written by

Mahdi Ben Rhouma
Mahdi Ben Rhouma

Full-Stack Dev — Next.js & Supabase

Solo developer building SaaS products with Next.js and Supabase. Writing about production patterns the official docs skip.

Remote