WhatBroke

npm run build fails but the dev server works fine

Any AI coding tool Last checked 2026-10-14

The dev server is permissive and lazy; the production build is strict and compiles everything. Code the agent wrote can run fine in dev and still fail type checking, linting, or prerendering at build time. Run the real build locally before you push — that is the only check that matches what your host runs.

What you saw

npm run dev is clean, the app works in the browser, and npm run build fails — type errors, Module not found, window is not defined, or a prerender error on a specific route.

Frequently discovered only when the deploy fails, minutes after you were told everything was working.

What it actually means

Dev and build are different pipelines, and the agent only ever saw the dev one succeed:

The fix

  1. Reproduce the real build locally. This is the single highest-value habit here:

    npm run build
    npm run start   # or: npx serve dist
  2. Read the first error only. Build failures cascade; fixing error one usually removes the next twenty. Do not paste the whole log at the agent and ask it to fix everything.

  3. For window is not defined, move the access out of module scope and behind an effect or a dynamic import:

    if (typeof window !== 'undefined') { /* browser-only */ }
  4. For Module not found that works locally, check the import's capitalisation against the real filename. Verify with git, which records the true case:

    git ls-files | grep -i button
  5. Verify a clean install matches your machine — this catches missing or misplaced dependencies:

    rm -rf node_modules
    npm ci
    npm run build
  6. Do not silence the check to make the build pass. Disabling type errors in the build config hides the failure until runtime, where it costs more.

How to stop it happening again

Add the build to your definition of done. Tell the agent in the project rules file: a task is not complete until npm run build passes.

Run type checking in the background during development (tsc --watch --noEmit) so type errors show up when they are written, not at deploy time.

Keep imports consistently cased and prefer a path alias (@/components/Button) over long relative chains.

Build on every push in CI, so the failure arrives attached to the commit that caused it rather than a week later.

Related questions

Should I just turn off type errors during build?

No. It converts a build failure you can see into a runtime failure your users see. If you need to ship urgently, fix the one error — it is almost always a two-line change.

Why does it only break on the host and not on my machine?

Usually filename case sensitivity, a Node version difference, or a dependency that exists in your node_modules but not in package.json. npm ci from a clean checkout reproduces all three.

The agent says it fixed it but the build still fails.

Have it paste the actual command output rather than describing it. Agents routinely report success from reasoning about the change instead of running the build.

Other things that break

What Broke This Week

One email, most Thursdays. New symptoms, tool updates that quietly break things, and one fix worth stealing. Unsubscribe in one click.