Module not found on Vercel, but it works locally
The error in your build logModule not found: Can't resolve './components/Header'
# or, at runtime in a Node function:
Error: Cannot find module '../lib/Utils'
Almost always a capitalization mismatch. Your laptop treats Header.tsx and header.tsx as the same file. Vercel builds on Linux, which does not.
Why it happens
Windows and macOS use case-insensitive file systems by default, so an import of ./components/Header happily loads header.tsx on your machine. Vercel runs builds on a case-sensitive Linux file system, where those are two different paths, so the build cannot find the file.
Two related causes give the same error: a file that never got committed (it is in .gitignore, or you forgot to add it), and a package you use but never added to package.json. AI coding agents hit all three often, because they create and rename files quickly.
Fix it by hand
- Find the exact path that failed. Open the failed deployment's build log and copy the path after
Can't resolveorCannot find module, plus the file that imports it. - See the name git actually stored. Vercel builds what is in git, not what is on your disk. Search it case-insensitively:
Compare it letter by letter with the import.git ls-files | grep -i headercomponents/header.tsxin git and./components/Headerin the import will fail on Vercel. - Fix the import or rename the file. Changing the import to match the file is the simplest fix. If you want to rename the file instead, do it in two steps through a temporary name, because a single case-only
git mvcan fail silently on Mac and Windows:git mv components/header.tsx components/header-tmp.tsx git mv components/header-tmp.tsx components/Header.tsx git commit -m "Fix Header file name case" - Make git report case changes from now on.
This only changes what git reports going forward. It does not fix names already committed, which is why step 3 matters.git config core.ignorecase false - If the file is missing from git entirely, check
.gitignore(git check-ignore -v path/to/filetells you which rule matches), then add and commit the file. - If it is a package, confirm it is listed in
package.jsonand that the lockfile is committed. Install it withnpm install the-packageso both files update, then commit them. - Redeploy and check the build log passes the step that failed.
Stop it happening again
- Run the production build on Linux before you merge, for example in a CI job, so case problems fail there and not on deploy day.
- Keep
core.ignorecaseset tofalsein every clone of the repo. - Pick one naming style for files (for example PascalCase for components) and have your agent follow it in your project rules file.
- After an agent renames files, run
git statusand check the rename was recorded.
Broke After Deploy $9
Broke After Deploy checks every import in your project against the real file names (capitalization included), finds imports of files git ignores, packages missing from package.json, and runtime packages stuck in devDependencies. Paste the build error and it points at the exact line.
- Checks your project for 37 known causes of "works locally, breaks in production" and runs your production build.
- Paste the error and it finds the cause in your code, then lists what will break next.
- Verdict first. Every finding shows the file and line, what it breaks, and the fix as a diff that is applied only with your OK.
Broke After Deploy: how it works, with examples · Install guide
Works with Claude Code, Claude.ai, Cursor, Codex and other agents that read SKILL.md files. No installs, no accounts, works offline. No-questions refund.