Blog
3 min read

npm run build Fails but npm run dev Works: Why and How to Fix It

Development mode is forgiving; production builds are strict. The common reasons a build fails when dev works — TypeScript and lint errors, case-sensitive imports, missing environment variables, server-only code in the browser, prerendering errors and memory — with the fix for each.

Your app works perfectly with npm run dev. Then npm run build — or your host's deploy — fails. This is extremely common, and it's not random: dev mode is designed to be forgiving, production builds are designed to be strict. (npm run dev vs build vs start)

Always read the first error in the build output; later errors are often consequences of it. (How to read an error message)

1. TypeScript errors

Dev servers often transpile TypeScript without type-checking it. next build and many CI setups do type-check, and fail on errors you never saw.

Run the checker yourself:

npx tsc --noEmit

Fix the errors rather than silencing them — they're often real bugs. (Type is not assignable to type, Property does not exist on type, Object is possibly undefined)

2. Lint errors

Some frameworks run ESLint during the build and fail on errors (not warnings). Run npm run lint locally to see them. (Linters and formatters)

3. Case-sensitive file names

Module not found: Can't resolve './components/Header'

…but the file is header.tsx. macOS and Windows ignore case; the Linux machine doing your build doesn't. Match the case exactly. If you renamed a file only by case, Git may not have noticed — use git mv header.tsx Header.tsx. (Cannot find module)

4. Missing environment variables

The build needs variables that exist in your local .env but not in your host's settings. Especially frontend variables (VITE_*, NEXT_PUBLIC_*), which are baked in at build time — they must be present during the build, not just at runtime. (Environment variable undefined?)

Add them in your hosting dashboard, then rebuild.

5. Prerendering errors (Next.js)

Error occurred prerendering page "/dashboard"

During the build, Next.js renders static pages ahead of time. If a page fetches data from an API or database that isn't reachable at build time, or uses browser-only things, the build fails.

  • Browser APIs during render → move into useEffect. (window is not defined)
  • Data that must be fetched live → make the page dynamic.
  • A database the build server can't reach → check connection settings or don't prerender that page. (SSR vs CSR vs SSG)

6. Server-only code imported in client code

Importing a Node module (fs, crypto, a database client) into a component that runs in the browser fails in the build:

Module not found: Can't resolve 'fs'

Keep server code in server components, API routes or server actions. (React Server Components explained)

7. Out of memory

FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory

Big builds can exceed Node's default memory, especially on small build machines. (JavaScript heap out of memory)

8. Different Node or package versions

Your host builds with a different Node.js version, or installs slightly different package versions.

  • Pin the Node version ("engines" in package.json, or an .nvmrc).
  • Commit your lock file and use npm ci in the build. (package-lock.json explained)

9. Dev-only dependencies

A package needed by the build is in devDependencies, and the host installs with --production. Either move it to dependencies or make sure the build step installs dev dependencies.

The habit that prevents most of this

Run the production build locally before pushing:

npm ci && npm run build

And put it in CI, so every push is checked. (Set up CI with GitHub Actions)


EasySpawn builds your app on the same Linux server it runs on, with the same Node version and environment, so a build that passes is a build that deploys. See how it works or join the waitlist.

Related: npm run dev vs build vs start · Why Does My App Work Locally but Not in Production? · React App Shows a Blank Page After Deploying · "Cannot Find Module"

Keep reading