Fix 'Next.js 15 requires Node.js 18.18' Build Error
Next.js

Fix 'Next.js 15 requires Node.js 18.18' Build Error

Next.js 15 drops support for older Node versions. Here is how to upgrade to Node.js 18.18.0 or later and fix build errors.

2026-06-05
8 min read
Fix 'Next.js 15 requires Node.js 18.18' Build Error

Photo by Pankaj Patel on Unsplash

You run next dev, next build, or next start and the process halts immediately with a hard stop in the terminal — no subtle bug, no partial compile:

text
You are using Node.js 16.20.0. For Next.js, Node.js version ">= v18.18.0" is required.

Next.js 15 is enforcing a hard requirement for Node.js 18.18.0 or newer. The fix is to upgrade your runtime with a version manager like nvm or volta and pin the engines field in package.json so nobody regresses it. This behavior is consistent across local development environments, Docker containers, and CI/CD pipelines like GitHub Actions. If you are deploying to Vercel, the platform usually handles this automatically, but self-hosted deployments or custom CI setups will fail until the runtime is updated.

What the version check actually does#

Next.js 15 dropped support for older Node.js releases and pinned the minimum to the 18.18.0 LTS baseline. Older 18.x patch releases and Node 16 are simply outside the supported range — treat it as a hard supported-versions floor the framework enforces, not a per-API quirk. The practical consequence is the same regardless of the deeper reason: you must run Node.js 18.18.0 or newer.

The framework checks the process.version string at startup. If the semantic versioning comparison fails, it throws the error you see. This check happens before the application code even loads, meaning you cannot bypass it with configuration flags or polyfills in your code. The logic essentially parses your Node version string and ensures it is greater than or equal to 18.18.0. This enforcement ensures that the underlying runtime can handle the concurrent features and edge runtime optimizations required for the App Router.

The requirement also reflects a broader shift: Next.js 15 leverages the native fetch API available in Node 18, removing the need for polyfills like node-fetch. This reduces bundle size and improves performance, but it requires a runtime that supports these web standards natively.

First, confirm the diagnosis:

bash
node -v

You will likely see a version like v16.x.x or v18.17.0.

Upgrading with nvm or Volta#

Relying on the system default Node version is risky for production engineering. Use a version manager to pin the correct version for your project.

nvm (macOS / Linux)#

nvm is the standard tool. Run the following commands to install the latest Long Term Support (LTS) version of Node 18, which satisfies the 18.18.0 requirement:

bash
nvm install 18
nvm use 18
nvm alias default 18

The alias default command ensures that new terminal sessions automatically use Node 18.

Volta (cross-platform)#

For a faster, tool-agnostic manager that works across platforms, I prefer Volta. It manages Node versions without changing your shell profile.

bash
volta install node@18

Volta automatically pins the version in a volta.json file in your project directory, ensuring anyone who clones the repo gets the right Node version immediately.

Pin the version with engines, .nvmrc, and tool files#

Upgrading your own machine is not enough — the next developer (or your CI server) can still run the project on Node 16. Three files prevent that:

engines in package.json:

json
{
  "name": "my-nextjs-app",
  "version": "1.0.0",
  "engines": {
    "node": ">=18.18.0",
    "npm": ">=9.0.0"
  }
}

If you are using yarn, you might need to enable the engines-strict option in your .yarnrc file to make this check fail-fast during installation.

.nvmrc or .node-version: place a file named .nvmrc in your project root containing the string 18. When you run nvm use, it automatically switches to that version.

volta.json or .tool-versions: if using Volta or asdf, commit the configuration file that pins the tool version. This ensures that npm install fails or warns if the wrong Node version is active.

When structuring large-scale applications, managing these environment configurations becomes part of your core architecture. I discuss how to organize these config files alongside your app router structure in How to Structure Your Next.js App Router Project for Scale.

Reinstall dependencies after switching versions#

Changing Node versions can sometimes break native dependencies or binaries inside node_modules. It is best practice to regenerate your lockfile and dependencies after a major version upgrade:

bash
rm -rf node_modules package-lock.json
npm install

At this point Next.js 15's startup logic will detect a valid process.version, allowing the server initialization to proceed past the version check and load your application configuration. Verify:

bash
npm run dev

You should see output similar to this:

text
  ▲ Next.js 15.0.0
  - Local:        http://localhost:3000
  - Environments: .env.local
 
 ✓ Ready in 1.2s

The "Ready" message confirms that the version check passed and the server compiled successfully. If you are using TypeScript, also run npm run build to ensure there are no type errors related to the Node types (sometimes @types/node needs updating as well).

Local works, CI fails: setup-node still on an old default#

Even if your local machine works, your GitHub Actions or GitLab CI might fail if the actions/setup-node step defaults to an older version. Update your workflow YAML file to explicitly request Node 18 or 20:

yaml
- name: Setup Node.js
  uses: actions/setup-node@v4
  with:
    node-version: '20'
    cache: 'npm'

Making CI the "source of truth" also catches drift in the other direction: if the build passes in CI but fails locally, it signals a local environment problem, not a project one. I cover how to integrate this into a robust Supabase and Next.js pipeline in Next.js & Supabase Masterclass: Robust CI/CD Pipelines with GitHub Actions.

Docker images pinned to node:16#

If you are deploying via Docker, your base image might be pinned to an old version (e.g., node:16-alpine). Update your Dockerfile to use a newer base image:

dockerfile
FROM node:18.18-alpine AS base
 
# Install dependencies only when needed
FROM base AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci

Always verify the specific tag exists on the Docker Hub to avoid build failures during deployment. For more on production deployment strategies, see Deploying Next.js + Supabase to Production.

Upgrade checklist#

  • Run node -v to check your current version.
  • Upgrade to Node 18.18.0+ using nvm, volta, or the official installer.
  • Add "engines": { "node": ">=18.18.0" } to package.json.
  • Delete node_modules and reinstall dependencies.
  • Update CI/CD workflows (actions/setup-node) to use Node 18+.
  • Update Docker base images to node:18 or node:20.
  • Run npm run dev and npm run build to verify success.

Frequently Asked Questions

|

Have more questions? Contact us

Written by

Mahdi Br
Mahdi Br

Full-Stack Dev — Next.js & Supabase

Solo developer building SaaS products with Next.js and Supabase. Writing about production patterns the official docs skip.

Remote

One email a month — no fluff

RLS gotchas, Next.js cache debugging, and the one Supabase setting that bit me last month.