How to Fix ‘Cannot Find Module’ Error in Node.js: A Complete 2026 Guide
If you are a developer, there is a near 100% chance you have stared at your terminal in frustration, only to be greeted by the infamous red text: Error: Cannot find module. It is the Node.js equivalent of a flat tire. It usually happens at the worst possible time—right in the middle of a deployment, when setting up a new machine, or when simply running a script that worked perfectly fine yesterday.
In this comprehensive guide, we are going to dive deep into exactly how to fix cannot find module error nodejs environments throw at us. We will start with the most common pitfalls and move our way down to advanced edge cases involving ES modules, TypeScript path aliases, and monorepo configurations.
Grab a coffee, and let’s debug this together.
Understanding the “Cannot Find Module” Error
Before we start slinging code and running commands, we need to understand why Node.js throws this error.
When you write require('./myFile') or import express from 'express', Node.js relies on a specific module resolution algorithm to find the requested file. If the algorithm exhausts all possible lookup locations without finding a matching file, Node.js throws an MODULE_NOT_FOUND error.
The error usually looks something like this:
node:internal/modules/cjs/loader:1042
const err = new Error(message);
^
Error: Cannot find module 'express'
Require stack:
- /Users/yourname/projects/my-app/server.js
at Module._resolveFilename (node:internal/modules/cjs/loader:1042:15)
at Module._load (node:internal/modules/cjs/loader:887:27)
at Module._resolveFilename (node:internal/modules/cjs/loader:1042:15)
at Function.Module._load (node:internal/modules/cjs/loader:887:27) {
code: 'MODULE_NOT_FOUND',
requireStack: [ '/Users/yourname/projects/my-app/server.js' ]
}
The error message gives us two vital pieces of information:
1. The module name: The file or package Node is trying to find.
2. The require stack: The file that made the failing request.
If you are searching for how to fix cannot find module error nodejs generates, the root cause almost always falls into one of these categories:
* Typographical errors in the file path.
* Missing dependencies in the node_modules folder.
* Missing or misconfigured package.json files.
* Conflicts between CommonJS (CJS) and ES Modules (ESM).
Let’s break down the solutions, starting with the most frequent offenders.
Step 1: Verify the File Path and Casing (The Silent Killer)
The absolute most common reason for this error is a simple typo. However, there is a sneaky variation of this bug that catches even senior developers off guard: Case Sensitivity.
If you are developing on a Windows or macOS machine, your filesystem is likely case-insensitive. This means ./UserController.js and ./userController.js are treated as the exact same file locally.
However, Linux (which runs 90% of production servers, Docker containers, and CI/CD pipelines) is strictly case-sensitive.
The Scenario
You create a file named UserController.js. In your routing file, you write:
// routes.js
const userController = require('./usercontroller.js'); // Notice the lowercase 'c'
This will work perfectly on your Mac. You commit the code, push it to GitHub, and your CI/CD pipeline deploys it to a Linux Ubuntu server. The moment the server starts, it crashes with Error: Cannot find module './usercontroller.js'.
The Fix
Always use exact casing. To make things easier, use modern IDE features or linting tools to enforce consistency.
// Corrected routes.js
const userController = require('./UserController.js');
Pro-Tip: If you accidentally commit a file with the wrong casing to Git, Git might not register the name change. You can force Git to recognize the casing change using the git mv command:
git mv usercontroller.js UserController.js
git commit -m "Fix casing for UserController"
Step 2: Reinstall Project Dependencies (node_modules)
Sometimes, the module isn’t missing because of a typo; it’s missing because it genuinely isn’t there. If you just pulled a repository from GitHub or experienced a sudden hard drive crash, your node_modules folder might be incomplete or corrupted.
The Clean Slate Approach
Never try to manually patch a broken node_modules folder. The best approach is to wipe the slate clean and reinstall everything.
Run the following commands in your terminal:
# 1. Delete the node_modules directory
# If you are on Mac/Linux:
rm -rf node_modules
# If you are on Windows (PowerShell):
Remove-Item -Recurse -Force node_modules
# 2. Delete the package-lock.json file to ensure no corrupted cache is used
rm package-lock.json
# (Windows: Remove-Item package-lock.json)
# 3. Clear the npm cache (Optional but recommended for stubborn issues)
npm cache clean --force
# 4. Reinstall your dependencies
npm install
By running npm install, npm will read your package.json file, resolve the dependency tree, and recreate the node_modules folder exactly as it should be.
Step 3: Check for Global vs. Local Installation Issues
Node.js packages can be installed locally (inside your project’s node_modules) or globally (accessible system-wide).
A common mistake is trying to require() a globally installed package in your local code without linking it first.
The Scenario
Let’s say you installed nodemon globally to watch your files:
npm install -g nodemon
Then, inside your Node.js application, you try to use it programmatically:
const nodemon = require('nodemon');
Node.js will throw a Cannot find module error because, by default, Node.js only looks in the local node_modules directories moving up the folder tree. It does not check the global node_modules path.
The Fix
If you need to use a package in your code, it must be installed locally, even if it is also installed globally.
# Install it locally instead of (or in addition to) globally
npm install nodemon
If you are writing a CLI tool and specifically want to use a global package, you can use the NODE_PATH environment variable to tell Node.js where to look, but this is considered an anti-pattern in modern Node.js development. Stick to local installations for project dependencies.
Step 4: Correct Missing package.json Dependencies
I see this scenario constantly when consulting for startups: a developer adds a new library, tests it locally, and everything works. They push the code. Five minutes later, the rest of the team is complaining about Cannot find module errors.
The Scenario
Why did it work for Developer A but not Developer B? Because Developer A ran npm install lodash instead of npm install --save lodash.
(Note: In modern versions of npm—version 5 and above—npm install <pkg> automatically adds it to package.json. However, if you are using older legacy projects or manually editing package files, this issue still persists).
If a package exists in your node_modules but is not listed in your package.json dependencies block, it is considered an “ephemeral” dependency. When another developer downloads the code and runs npm install, npm won’t install that package, resulting in the error.
The Fix
Check your package.json file. If the missing module is missing from the dependencies or devDependencies object, you need to add it.
// package.json
{
"name": "my-awesome-app",
"version": "1.0.0",
"dependencies": {
"express": "^4.19.2",
"lodash": "^4.17.21" // Make sure this is here!
}
}
Then, run npm install to sync the node_modules folder with the package.json file.
Step 5: Navigating ES Modules (ESM) and CommonJS (CJS) Conflicts
As of Node.js versions 18, 20, and the newer 22+ releases, ES Modules (using import/export) have become the standard. However, the ecosystem is still heavily populated with CommonJS packages (using require/module.exports). This transition period has spawned a whole new breed of Cannot find module errors.
Scenario 1: Missing File Extensions in ESM
In CommonJS, you could omit the file extension:
// CommonJS (Works fine)
const utils = require('./utils');
But in ES Modules, if you have "type": "module" in your package.json, file extensions are mandatory. Node.js will not guess the extension.
// ES Modules (Will throw 'Cannot find module')
import utils from './utils';
// ES Modules (Correct - requires .js extension)
import utils from './utils.js';
Scenario 2: Importing Built-in Node Modules
In Node.js version 20 and 22+, certain built-in modules that used to be available via require() must now be imported using the node: prefix when using ESM.
If you see Error: Cannot find module 'fs', check your import statement.
// Might fail in strict ESM environments
import fs from 'fs';
// The Modern, correct way
import fs from 'node:fs';
Scenario 3: Subpath Exports
Modern npm packages use the exports field in their package.json to define entry points. If you try to import a deep file that the package author hasn’t explicitly exposed, Node.js will throw a module not found error.
For example, trying to do import something from 'some-package/dist/internal-file.js' might fail if some-package doesn’t list that path in its exports map.
The Fix: Always import from the root of the package, or check the package’s official documentation for the correct subpath import syntax.
Step 6: Resolve TypeScript Path Aliases
If you are using TypeScript (which compiles down to Node.js), the Cannot find module error can be incredibly frustrating when it happens at runtime, even though your IDE (like VS Code) shows no errors.
The Scenario
In your tsconfig.json, you set up path aliases to avoid ugly relative paths like ../../../utils/math.
// tsconfig.json
{
"compilerOptions": {
"baseUrl": "./src",
"paths": {
"@utils/*": ["utils/*"]
}
}
}
In your TypeScript file, you write:
import { addNumbers } from '@utils/math';
VS Code loves this. It autocompletes perfectly. But when you run tsc to compile to JavaScript, and then execute the code with node dist/index.js, you get: Error: Cannot find module '@utils/math'.
Why? Because Node.js does not understand TypeScript path aliases out of the box. When TypeScript compiles to JavaScript, it leaves the @utils/math import exactly as it is, and Node.js has no idea how to resolve @utils.
The Fix
You have two main solutions here.
Option A: Use a TypeScript Runtime
Instead of compiling to JS, use a runtime like tsx or ts-node that understands tsconfig.json paths natively.
“`bash
npm install -D tsx
n