Founder & Lead Engineer, RAITHub
Short answer: next-auth 4 declares an optional peer dependency on an older nodemailer. The latest release, 4.24.15, wants ^7.0.7, so a project on nodemailer 10 fails a strict npm install with ERESOLVE. If you only use next-auth's credentials or OAuth login, add an npm overrides entry that points next-auth's nodemailer at your own version. Don't downgrade nodemailer, because older versions carry published security advisories.
This happened to the RAITHub website on 27 September 2026. A security upgrade had moved nodemailer from v7 to v10 to clear its advisories. Every check passed on our machines, and then the Vercel build failed in 3 seconds. Below is the exact error, why the local checks missed it, the options we weighed, and how we proved the fix.
What does the error look like?
The build stops during npm install, before any of your code runs. These are the key lines from our Vercel build log:
npm error code ERESOLVE
npm error ERESOLVE could not resolve
npm error nodemailer@"^10.0.10" from the root project
npm error Could not resolve dependency:
npm error peerOptional nodemailer@"^7.0.7" from next-auth@4.24.15
npm error Conflicting peer dependency: nodemailer@7.0.13
npm error Fix the upstream dependency conflict, or retry this command with --force or --legacy-peer-deps
Error: Command "npm install" exited with 1
Read it from the bottom up. Your project asks for nodemailer 10. next-auth says that, if nodemailer is present, it must be version 7. npm 7 and later treat peer dependencies strictly, including optional ones once the package is installed, so npm refuses to build a dependency tree that breaks either rule.
Why did it pass locally but fail on Vercel?
Our local checks ran npm ci, but Vercel ran npm install. On npm 11.12.1 with Node.js 24.15, npm ci installed the committed lockfile and succeeded. npm install re-resolves the tree, re-checks peer ranges and fails. We reproduced it exactly by running Vercel's command on a clean clone.
| Command | What it does | Result on our repo (27 Sep 2026) |
|---|---|---|
npm ci | Installs exactly what the lockfile says | Succeeded |
npm install | Resolves the tree again and checks every peer range | Failed with ERESOLVE |
npm install --dry-run | Same resolution, without writing anything | Failed with the same error, so it is a cheap way to test |
The lesson is broader than this one package: run the install command your deploy target runs. A check that runs a different command proves something about a different environment. We now reproduce deploy failures on a clean clone outside the working folder, with the same command the platform uses.
Can I just upgrade next-auth?
No, not within version 4. We checked every next-auth release from 4.20 onward: 25 of them declare nodemailer ^6.6.5 and the latest 4 declare ^7.0.7. None accepts nodemailer 10. The next major version (Auth.js, next-auth 5) is a larger migration with a different configuration API, so it is not a quick fix for a broken deploy.
Why not downgrade nodemailer to v7?
Because v7 is the version the security upgrade was removing. When we checked npm's advisory database on 27 September 2026, nodemailer 7.0.13 matched a high-severity advisory (GHSA-p6gq-j5cr-w38f, affecting versions up to 9.0.0) that allows arbitrary file reads and server-side request forgery, plus moderate ones. Downgrading would have made the build pass by reopening the hole.
Which fix is right?
If your app never sends email through next-auth itself, use a scoped overrides entry. Here are the four options we weighed:
| Option | Effect | Verdict |
|---|---|---|
| Downgrade nodemailer to 7 | Build passes | Rejected: brings back a high-severity advisory |
--legacy-peer-deps or legacy-peer-deps=true in .npmrc | Build passes | Rejected: turns off peer checks for every package, which hides the next real conflict |
| Migrate to next-auth 5 | Removes the old peer range | Right long-term, but too big for a hotfix |
Scoped npm overrides | Only next-auth's view of nodemailer changes | Chosen |
How do you write the overrides entry?
Add this to package.json. The $nodemailer value means "use whatever version the root project depends on", so the two can never drift apart.
{
"dependencies": {
"next-auth": "^4.24.13",
"nodemailer": "^10.0.10"
},
"overrides": {
"next-auth": {
"nodemailer": "$nodemailer"
}
}
}
The override is scoped to next-auth. Nothing else in the tree changes, and peer checking stays on for everything else.
Is the override safe?
It is safe when next-auth never loads nodemailer, which is true unless you use its Email (magic link) provider. We checked our code: the only provider was CredentialsProvider. The app's own email code imports nodemailer 10 directly. So the override changes what npm accepts, not what runs.
If you do use the Email provider, next-auth will call nodemailer 10 through an API it was written against v6 or v7. Test sign-in by email end to end before relying on the override, or plan the move to next-auth 5.
How did we prove the fix before pushing?
We ran the same steps a fresh Vercel build runs, on a clean clone outside our working folder:
- Deleted
node_modulesand rannpm install. It exited 0 with no ERESOLVE. - Ran
npm ls. It exited 0, and next-auth now dedupes to nodemailer 10.0.10 instead of reporting an invalid peer. - Ran
npm audit. It reported 0 vulnerabilities. - Ran the type-check, lint, the full test suite (381 tests at the time) and a production
next build. All passed.
npm ls also surfaced a second, milder mismatch. @auth/core, pulled in by an unused @auth/prisma-adapter, wanted nodemailer ^7.0.7 || ^8.0.5. We covered it with the same override at first, then removed the unused adapter in the next security pass, which made that override unnecessary. Unused dependencies are still attack surface and still take part in dependency resolution.
How do you stop this happening again?
- Run the deploy's install command in CI. Use
npm installif that is what your host runs, or switch the host tonpm ciso both match. - Check peers after every dependency upgrade. Run
npm lsand treat "invalid" as a failure, not a warning. - Leave a comment by every override saying why it exists and when it can be removed. Ours goes away when we move to next-auth 5.
- Remove unused packages. Each one takes part in resolution, even if your code never imports it.
This is the kind of fix we do in code rescue: reproduce the exact failure, understand the constraint, and make the smallest change that keeps the security fix. For another bug our tests missed and a review caught, read how Zod 4 .partial() silently wiped admin data. For how we gate releases in general, see how RAITHub tests software. If your deploy is stuck right now, tell us about it as a "Fix a specific issue" request.
Last reviewed: 27 September 2026. Tested with npm 11.12.1, Node.js 24.15.0, next-auth 4.24.15 and nodemailer 10.0.10.
Frequently asked questions
Why does npm fail on an optional peer dependency?
Since npm 7, peer dependencies are checked strictly. An optional peer need not be installed, but if the package is present, its version must still satisfy the declared range. nodemailer 10 is outside next-auth 4's range, so npm stops.
Why does npm ci pass when npm install fails?
In our case, npm ci installed the committed lockfile as-is and succeeded, while npm install re-resolved the dependency tree and re-checked peer ranges. If your host runs npm install, test with npm install.
Is --legacy-peer-deps a safe fix?
It gets the build through, but it turns off peer checking for every package in the project. A scoped overrides entry fixes only the known conflict and keeps npm warning you about new ones.
What does "$nodemailer" mean in npm overrides?
It is a reference to the version your root package.json declares for nodemailer. The override always follows your own dependency, so upgrading nodemailer later updates next-auth's copy too.
Does the override break next-auth email sign-in?
It can if you use the Email (magic link) provider, because next-auth 4 was written against older nodemailer versions. If you only use credentials or OAuth providers, next-auth never loads nodemailer. Test email sign-in end to end if you use it.
Which next-auth versions accept nodemailer 10?
None of the next-auth 4 releases do. On 27 September 2026, releases 4.20 and later declared nodemailer ^6.6.5 or ^7.0.7. Moving to next-auth 5 (Auth.js) is the long-term way out of the old peer range.
Can RAITHub fix a broken deploy like this?
Yes. Choose "Fix a specific issue" on the RAITHub contact form and paste the error. The first step is a free 15-minute technical audit to confirm the cause and the scope before any paid work.
Related posts
Ready to discuss your project?
Book a free 15-minute technical audit with our engineering team.