The error Error: Cannot find module ‘x’ (or Cannot find module ‘x’ or its corresponding type declarations in TypeScript) is extremely common. It has several distinct causes โ here’s how to diagnose and fix each.
๐ Table of Contents
- Cause 1: Package Not Installed
- Cause 2: Wrong Import Path (Relative Imports)
- Cause 3: Missing Type Declarations (TypeScript)
- Cause 4: tsconfig Path Aliases Not Configured
- Cause 5: ESM vs CommonJS Extension Issues
- Cause 6: Module Installed but Not Built (Monorepo/Workspace)
- Diagnostic Checklist
- Node's Module Resolution โ How It Works
- Frequently Asked Questions
- Conclusion
Cause 1: Package Not Installed
# The most common cause โ you forgot to install it
npm install express
# Reinstall everything if node_modules is corrupted
rm -rf node_modules package-lock.json
npm install
# Verify it's actually in package.json
npm list express
Cause 2: Wrong Import Path (Relative Imports)
// ๐ Wrong path
import { helper } from './utils/helper'; // but file is at ./lib/helper
// โ
Fix: correct the relative path
import { helper } from './lib/helper';
// Common mistakes:
// - Missing ./ for local files: import x from 'utils' looks in node_modules
// - Wrong case: ./Helper vs ./helper (case-sensitive on Linux!)
// - Missing file extension in ESM (see Cause 5)
Cause 3: Missing Type Declarations (TypeScript)
# Error: Cannot find module 'lodash' or its corresponding type declarations
# The package works but has no bundled types. Install @types:
npm install --save-dev @types/lodash
# For packages that will never have types, declare them:
# create src/types/untyped-module.d.ts
declare module 'some-untyped-package';
Cause 4: tsconfig Path Aliases Not Configured
// You use import { x } from '@/utils' but it's not configured
// tsconfig.json โ add path mapping
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
}
}
}
// For runtime (Node), you also need tsconfig-paths or a bundler:
// npm install -D tsconfig-paths
// node -r tsconfig-paths/register dist/index.js
// Or use tsx which handles this automatically
Cause 5: ESM vs CommonJS Extension Issues
// In ESM ("type": "module" in package.json), you MUST include .js extension
// even when importing .ts files:
// ๐ Fails in ESM
import { helper } from './utils/helper';
// โ
Correct in ESM
import { helper } from './utils/helper.js'; // yes, .js even for .ts source
// package.json
{
"type": "module"
}
// tsconfig.json
{
"compilerOptions": {
"module": "ESNext",
"moduleResolution": "bundler" // or "nodenext"
}
}
Cause 6: Module Installed but Not Built (Monorepo/Workspace)
# In a monorepo, the dependency package hasn't been built yet
# Cannot find module '@myorg/shared'
# Build the dependency first
npm run build --workspace=@myorg/shared
# Or build all packages (Turborepo/Nx)
turbo build
npx nx run-many --target=build
Diagnostic Checklist
- Is it installed? Run
npm list <module> - Is the path correct? Check case sensitivity and relative path
- Does it need @types? Try
npm i -D @types/<module> - ESM issue? Add
.jsextensions if"type": "module" - Path alias? Check tsconfig
pathsand runtime resolver - Restart the TS server in your editor (VS Code: Cmd+Shift+P, then “Restart TS Server”)
Node’s Module Resolution โ How It Works
// import 'foo' (no ./) โ Node looks in:
// 1. Core modules (fs, path, http)
// 2. node_modules in current dir
// 3. node_modules in parent dirs, up to root
// import './foo' (with ./) โ resolves relative to current file
// Looks for: ./foo.js, ./foo.json, ./foo/index.js, etc.
// Understanding this explains most "cannot find module" errors:
// - No ./ means Node searches node_modules (fails if it's a local file)
// - ./ means relative path (fails if the path is wrong)
Frequently Asked Questions
Q: Why does it work locally but fail on the server/CI?
A: Usually case sensitivity โ macOS/Windows are case-insensitive, Linux is not. ./Helper works locally but fails on Linux if the file is ./helper. Always match exact case.
Q: I installed the package but still get the error. Why?
A: Restart your editor’s TypeScript server, or the dev server. Also check the package is in dependencies, not just installed locally without saving. Delete node_modules and reinstall if unsure.
Q: What’s the difference between the module error and type declaration error?
A: “Cannot find module” alone = the JS module isn’t found. “…or its corresponding type declarations” = the module exists but TypeScript can’t find types. The second needs @types/x or a .d.ts declaration.
Q: How do I fix this in a Docker build?
A: Ensure npm install runs inside the container (don’t copy host node_modules). Copy package.json first, install, then copy source โ this also improves Docker layer caching.
Q: Should I use “moduleResolution”: “node” or “bundler”?
A: In 2026, use "bundler" for projects built with Vite/esbuild/webpack (no extension needed), or "nodenext" for pure Node ESM (extensions required). Avoid the legacy "node" for new projects.
Conclusion
“Cannot find module” almost always comes down to one of: the package isn’t installed, the import path is wrong (check case!), missing @types, ESM extension requirements, or unconfigured path aliases. Work through the diagnostic checklist top to bottom โ npm list, verify the path, check for @types, and restart your TS server. Ninety percent of cases resolve in the first three steps.
๐ You might also like
๐ Share this article




โ๏ธ Leave a Comment