Skip to content
NewHost
Menu

Next.js or Node.js Deploy Failed? A Troubleshooting Checklist

Why Next.js and Node.js deploys fail - Git access, npm ci and lockfiles, build errors, env variables, start files and Node versions - and how to fix each.

By NewHost team · · 6 min read

When a Next.js or Node.js deployment fails, the cause is almost always in one of five places: getting the code (Git access or the branch), installing dependencies (npm ci and the lockfile), building (type errors or missing build-time variables), starting the app (the wrong start file, or a crash on boot) or the runtime environment (Node.js version, environment variables, database access). Work through them in that order, reproduce the failure on your own machine with a clean install, fix it, push again.

This checklist goes through each stage with the errors you are likely to see and what they mean.

Start with the deployment log

Before changing anything, read the log of the failed deployment from start to finish. On NewHost, each deployment's log lists the steps in order, marks each one as done or failed, and shows Git's own error message when a Git step fails. The first failed step is where to look; anything after it is usually a consequence.

Also note what changed since the last successful deploy: a new dependency, a Node.js version change, a new environment variable, a renamed branch. The answer is usually in that diff.

Stage 1 - Getting the code

Typical symptoms: the deployment fails at the fetch or deploy-files step, with messages such as Permission denied (publickey), Repository not found or couldn't find remote ref.

  • Private repository without access. The server needs permission to read the repo. On NewHost, connect GitHub under Integrations with a GitHub account that can access the repository (an organisation may need to approve NewHost first); for other Git hosts, deploy from a public repository URL or open a support ticket.
  • Wrong branch name. main and master are different branches. Check the branch configured for the app matches the one you push to.
  • Repository URL typo or a moved repository. Renaming or transferring a repository changes its URL.

Stage 2 - Installing dependencies

Typical symptoms: errors from npm ci such as npm ci can only install packages when your package.json and package-lock.json are in sync, or ERESOLVE unable to resolve dependency tree.

  • Lockfile out of sync. npm ci installs exactly what package-lock.json says and refuses to run if it disagrees with package.json. Run npm install locally, commit the updated lockfile and push.
  • No lockfile at all. npm ci needs one. Commit package-lock.json, or change the install command to npm install (less reproducible).
  • Mixed package managers. If the repo has yarn.lock or pnpm-lock.yaml but the install command is npm ci, pick one tool and commit only its lockfile.
  • Peer dependency conflicts. Fix the versions rather than reaching for --force. --legacy-peer-deps is a last resort, not a habit.
  • Private packages. Installing from a private registry needs an access token as an environment variable and an .npmrc that reads it.

Stage 3 - Building

Typical symptoms: next build stops with Type error:, Module not found, or Error occurred prerendering page.

  • Type errors. next build fails on TypeScript errors by default. Run npm run build locally; the error points at a file and line.
  • Case-sensitive imports. import Header from "./header" works on Windows and macOS when the file is Header.tsx, then fails on a Linux server. Match the case exactly.
  • Missing build-time variables. Anything starting with NEXT_PUBLIC_ is baked into the JavaScript at build time. If it isn't set when the build runs, the value is undefined in the browser, or the build fails if your code checks for it. See Next.js environment variables in production.
  • Prerendering needs data that isn't there. A page that fetches from a database or API during the build fails if that service isn't reachable from the build. Make the page dynamic, or handle the failure and fall back gracefully.
  • Memory. Large builds can run out of memory, which shows up as JavaScript heap out of memory or a build that stops abruptly. Remove heavy unused dependencies, and check that big data files aren't being bundled. If the app has simply outgrown its plan, a plan with more RAM helps.

Stage 4 - Starting the app

Typical symptoms: the deploy succeeds but the site shows an error page, or the app keeps restarting.

  • Wrong startup file. For Next.js with output: "standalone", the server is .next/standalone/server.js, and the public and .next/static folders must be copied next to it, or pages load without CSS and images. Our guide to Next.js standalone output covers the details. For Express, the startup file is whatever file calls app.listen().
  • Hard-coded port. Listen on the port the platform provides: app.listen(process.env.PORT || 3000). Hard-coding 3000 works locally and can fail in production.
  • Crash on boot. The app throws during startup because an environment variable is missing, the database is unreachable or a file it expects isn't there. Validate required variables at startup and print a clear message naming the missing one, without printing its value.
  • Dev dependencies at runtime. Something your app needs at runtime is listed under devDependencies. Move it to dependencies.

Stage 5 - The runtime environment

  • Node.js version. If your code or a dependency needs a newer Node.js, set the version in the app's settings to match what you use locally. On NewHost you choose the version per application. Add an engines field to package.json so the requirement is written down:
{
  "engines": { "node": ">=22" }
}
  • Environment variables differ. Production has different values from your .env.local. Compare the names one by one; a typo in a variable name is a common cause.
  • Database connection. Check the host, port, user, password and database name, and that the database user has the permissions your migrations need. Connecting Node.js to MySQL with Prisma covers connection strings.

Reproduce it locally, the way the server does it

Most "it works on my machine" problems disappear when you build the way a server does: a clean install, a production build and the production start command.

rm -rf node_modules .next
npm ci
NODE_ENV=production npm run build
NODE_ENV=production PORT=3000 node .next/standalone/server.js

With standalone output, copy public and .next/static into .next/standalone first; without standalone output, use your own start command in the last line. If this fails on your machine, you have found the problem without touching the server.

Push the fix and redeploy

Fix the cause, commit, and push to the deployment branch. With auto-deploy, the push starts a new deployment; you can also start one with Redeploy in the dashboard. If you use preview deployments per branch, test risky changes on a branch first; see preview deployments explained.

If the log shows a step failing on the platform's side rather than in your code, or the same deployment fails repeatedly for no reason you can find, open a support ticket and include the application name and the time of the failed deployment.

Frequently asked questions

The build works locally but fails on the server. Why?

Usually a difference in environment: a missing environment variable, a different Node.js version, case-sensitive file names on Linux, or a lockfile that doesn't match. A clean install and production build on your own machine reproduces most of these.

Why does my Next.js site load without styles after deploying?

With standalone output, the public and .next/static folders must be copied next to server.js. Without them, HTML loads but CSS, JavaScript and images return 404.

Should I commit package-lock.json?

Yes. It makes installs reproducible and is required by npm ci.

How do I avoid broken deploys in the first place?

Run the build in CI on every pull request, deploy previews from branches, and keep the production branch for code that has already built successfully. Simple CI/CD for small teams shows a minimal setup.

Deploy Next.js and Node.js apps from Git to South African servers with NewHost Next.js hosting: choose your Node.js version, set encrypted environment variables and redeploy from the dashboard.

Related guides

Ready to launch on NewHost?

Choose a plan and go live today, or tell us what you need and we'll recommend the right setup.