The Error
Error: Cannot find module 'express'
Require stack:
- /home/user/myapp/app.js
at Function.Module._resolveFilename (node:internal/modules/cjs/loader:933:15)
at Function.Module._load (node:internal/modules/cjs/loader:778:27)
at Module.require (node:internal/modules/cjs/loader:1005:19)
at require (node:internal/modules/cjs/helpers:102:18)
Node.js throws this when require() or import can't find what you're asking for. Three main culprits: a package was never installed, a local file path is wrong, or node_modules got corrupted somehow.
Root Causes
- Package not installed โ
npm installwas never run, or ran in a different directory - Wrong relative path in
require('./someFile')โ off by one folder level - Corrupted or incomplete
node_modules(partial install, disk full, etc.) - Package listed in
package.jsonbut never actually installed locally - Node.js version mismatch โ the package requires Node 18+ but you're on 16
- Global package referenced in a local project (or the reverse)
Fix 1: Install the Missing Package
Nine times out of ten, this is the fix. The package simply isn't there:
# npm
npm install express
# yarn
yarn add express
# pnpm
pnpm add express
Installing a dev-only tool like Jest or TypeScript? Use --save-dev so it doesn't bloat production builds:
npm install --save-dev jest
Quick sanity check:
node -e "require('express'); console.log('OK')"
Fix 2: Nuke and Reinstall node_modules
Sometimes node_modules gets out of sync with package-lock.json โ partial installs, switching branches, or a failed upgrade can all cause this. The clean solution:
rm -rf node_modules package-lock.json
npm install
On Windows (PowerShell):
Remove-Item -Recurse -Force node_modules
Remove-Item package-lock.json
npm install
This wipes everything and rebuilds from scratch. A fresh npm install typically takes 30โ90 seconds for most projects.
Fix 3: Check You're in the Right Directory
A classic trap. You run the app from a parent folder โ but node_modules lives in the project subfolder, not where you're standing:
# Wrong โ node_modules is not here
cd /home/user
node myapp/app.js
# Right
cd /home/user/myapp
node app.js
Confirm node_modules and package.json share the same directory:
ls node_modules | grep express
Fix 4: Fix a Wrong Local File Path
When the error says Cannot find module './utils', Node.js is looking for a file relative to the current module โ and it's not where you think it is.
// Broken: file doesn't exist at this path
const utils = require('./utils');
// Try one level up
const utils = require('../utils');
// Or inside a subfolder
const utils = require('./helpers/utils');
Not sure which directory Node.js thinks you're in? Print it:
console.log(__dirname); // absolute path of the current file
Fix 5: TypeScript / ESM Path Issues
TypeScript with "moduleResolution": "NodeNext" has a quirk: you import .js extensions even though the source files are .ts. It looks wrong but it's correct โ the compiler resolves it at build time.
// This imports foo.ts โ the .js extension is intentional
import { foo } from './foo.js';
Running ts-node and hitting module errors? Try the ESM flag:
npx ts-node --esm app.ts
Or switch to the more forgiving resolver in tsconfig.json:
{
"compilerOptions": {
"moduleResolution": "node"
}
}
Fix 6: Global vs Local Package Conflict
Tools like nodemon or ts-node are often installed globally, but package.json scripts expect a local copy. Install them as dev dependencies to keep things consistent across machines:
npm install --save-dev nodemon ts-node
To see where a package lives:
npm list express # local install
npm list -g express # global install
Fix 7: NODE_PATH for Monorepos
Custom setups and monorepos sometimes need explicit module resolution hints. If Node.js can't find a shared package across workspace folders:
# One-off run
NODE_PATH=./src node app.js
# Bake it into package.json scripts
"scripts": {
"start": "NODE_PATH=./src node app.js"
}
Verification Steps
- Confirm the package is listed:
cat package.json | grep express - Confirm it's physically installed:
ls node_modules/express - Test the require directly:
node -e "require('express'); console.log('loaded')" - Run your app:
node app.jsโ the error should be gone
Prevention
- Commit
package.jsonandpackage-lock.jsonโ never commitnode_modules - After cloning a repo or pulling changes with new deps, run
npm installimmediately - Add
node_modules/to.gitignoreโ without this, repos balloon by hundreds of MB - Use
npm ciin CI/CD pipelines; unlikenpm install, it respects the lockfile exactly - Pin a minimum Node.js version in
package.jsonto catch engine mismatches early:"engines": { "node": ">=18" }

