Blog
3 min read

Module not found: Can't resolve — How to Fix It (Next.js, Vite, webpack)

"Module not found: Error: Can't resolve 'x'" means your bundler couldn't find a file or package you imported. The fixes for each cause: a package that isn't installed, wrong relative paths, case-sensitive file names that work on Mac but fail on Linux, path aliases like @/, and Node built-ins imported in browser code.

Your build stops with something like:

Module not found: Error: Can't resolve 'axios' in '/app/src/lib'
Module not found: Can't resolve './components/Header'
Failed to resolve import "@/utils/format" from "src/App.tsx"

All of these mean the same thing: an import points at something the bundler (webpack, Turbopack or Vite) can't find. The fix depends on what kind of thing it is.

(If you see Cannot find module from Node.js itself rather than a bundler, see Cannot Find Module.)

Cause 1: The package isn't installed

If the name has no ./ or @/ in front — 'axios', 'date-fns', '@supabase/supabase-js' — it's a package from npm.

npm install axios

Check it's listed in package.json. AI tools often write imports for packages they forgot to add. And if a package was installed only on your machine (npm install without saving), the server's fresh install won't have it. (npm and package.json Explained)

Before installing a package an AI suggested, check it actually exists and is the real one — hallucinated package names are a known attack vector. (AI Hallucinated Packages)

Cause 2: The relative path is wrong

./ means "this folder", ../ means "one folder up". If src/pages/Home.tsx imports './components/Header', the bundler looks for src/pages/components/Header — probably wrong. It should be '../components/Header'. (File Paths Explained)

Cause 3: Capital letters (works locally, fails in production)

This is the classic. macOS and Windows file systems usually ignore case; Linux doesn't. So this works on your laptop and fails on the server:

import Header from './components/header'   // file is Header.tsx

Make the import match the file name exactly. If you renamed a file only by case, git may not have noticed — use git mv header.tsx Header.tsx. (Why App Works Locally but Not in Production)

Cause 4: A path alias isn't configured

Imports like '@/utils/format' rely on an alias that maps @/ to src/. It needs to be set up for both TypeScript and the bundler:

// tsconfig.json
{
  "compilerOptions": {
    "paths": { "@/*": ["./src/*"] }
  }
}

Next.js reads tsconfig.json paths automatically. Vite needs the alias too, in vite.config.ts (or a plugin such as vite-tsconfig-paths):

import path from 'node:path'
import { defineConfig } from 'vite'
export default defineConfig({
  resolve: { alias: { '@': path.resolve(__dirname, './src') } },
})

Cause 5: Node built-ins in browser code

Can't resolve 'fs', 'path', 'crypto' or 'child_process' means browser code imported something that only exists in Node.js. Usually a server-only file got imported by a client component. Move that code to the server side (an API route, a server action or a server component). (Frontend vs Backend)

Cause 6: Wrong file extension or missing index

Imports usually omit extensions, and the bundler tries .js, .ts, .tsx and folder index files. If the file is .mjs, .cjs or something unusual, include the extension. (ESM vs CommonJS)

When nothing obvious is wrong

npm ci

npm ci reinstalls dependencies from your existing lockfile. Then clear build caches like .next or node_modules/.vite and try again. Keep package-lock.json: deleting it resolves new versions and can introduce unrelated changes or malicious releases. (package-lock.json Explained)

The summary

  • No ./ → install the package. With ./ → fix the path.
  • Match capital letters exactly — Linux is case-sensitive.
  • @/ needs an alias in tsconfig.json (and Vite config). fs/path errors mean server code leaked into the browser.

EasySpawn builds your app on the same Linux server it runs on, so case-sensitivity and missing-package surprises show up while you work — and Claude Code can fix them before you deploy. See how it works or join the waitlist.

Related: npm run build Fails · node_modules Explained · What Is Vite? · Webpack vs Vite

Keep reading