
Fix Next.js 16.3 standalone output failing on Vercel
A hands-on fix for the Next.js 16.3 ENOENT trace-file error on Vercel, with checks for Docker and self-hosted standalone builds.
This is one of those errors where the build looks fine for ages, then right at the end it just gives up. The app compiles. Pages get generated. Then Vercel runs onBuildComplete and complains that .next/next-server.js.nft.json is not there.
If your project is on Next.js 16.3 and you've output: 'standalone' in the config, this is probably the same thing. The fix is not big, but the reason is a little weird.
The short fix
Make Vercel use its normal output, and only turn on standalone when you're building the thing that will actually run server.js:
import type { NextConfig } from 'next'
const nextConfig: NextConfig = {
output: process.env.VERCEL ? undefined : 'standalone',
}
export default nextConfigVercel sets VERCEL=1 in the build environment. So on Vercel, output becomes undefined. On a Docker or plain Node build, VERCEL is not set and standalone stays on.
Put this in next.config.ts, commit it, and make a Vercel preview. The preview part matters. A local build can check the if statement, but it can't really copy Vercel's adapter step.
Before you use it, check the error
I would only use this workaround if these things line up:
You're on Next.js 16.3.0, or one of the close 16.3 canary builds.
Your config has output: standalone.
Vercel gets through the normal build and page generation.
The failure happens in onBuildComplete.
The missing file is .next/next-server.js.nft.json.
The upstream issue is #96646. It's a small reproduction, and the report says the same app works on 16.2.11 and works locally on 16.3. Removing standalone fixes the Vercel deployment.
Running onBuildComplete from Vercel
Error: ENOENT: no such file or directory, open
'/vercel/path0/.next/next-server.js.nft.json'If you see Module Factory Is Not Available instead, stop here. Different problem. That one is related to Turbopack hot reload, not this trace file.
Why this happens
There are two build things getting mixed together.
Vercel has a Next.js adapter. It takes the build output and turns it into the deployment that Vercel runs. You normally don't need a standalone server for that.
Standalone is for the other case. You build Next.js, copy the small server and the traced files into a Docker image, and start server.js yourself.
In the 16.3 change, Next.js stopped making the whole-server trace files when an adapter is active. That's fine for adapters because they don't use those files. But another part of the build still expected the file when standalone was also enabled.
So one step skips the file, and the next step tries to read it. That's why the error comes late. It doesn't mean your app code is broken.
Test both build paths
Don't only run pnpm build and call it good. Check the output for the thing that will run it.
Vercel build
This is a local check for the Vercel branch:
rm -rf .next
VERCEL=1 pnpm build
test ! -d .next/standaloneYou should get a successful build and no .next/standalone directory. After that, push a preview. That's the real check for this bug.
Docker or self-hosted build
Now do the opposite. Remove VERCEL from the environment and build clean:
rm -rf .next
env -u VERCEL pnpm build
test -d .next/standaloneFor a normal one-package app, start it like this:
node .next/standalone/server.jsIf it's a monorepo, server.js might be deeper in the folder. Have a look instead of assuming the path.
Also remember that standalone doesn't always copy public and .next/static for you. Your Dockerfile needs to do that if your setup needs them. Then request a real page, a static file, and an image. A green build by itself doesn't catch all the silly container mistakes.
If Vercel is your only target
Then you can probably remove output: 'standalone' completely. Vercel already knows how to build and run the app. The conditional config is mainly useful when the same repo also makes a Docker image or runs on your own Node server.
There's no prize for keeping standalone on when nothing is using it.
If you can't change the config
If one config has to stay exactly the same for now, pin Next.js to the previous minor:
pnpm add --save-exact next@16.2.11Use the exact version, not ^16.2.11. The range can move you to another release without you noticing. Run your normal tests and check both deployment targets before you trust it.
Things I would not try first
A few fixes sound plausible but are aimed at something else:
outputFileTracingRoot changes where tracing starts. It doesn't create a trace file that the adapter skipped.
Deleting .next is good before testing, but it doesn't change the 16.3 and Vercel combination.
Ignoring the ENOENT can give you a standalone server that builds but then crashes when it starts.
NEXT_ADAPTER_PATH is an internal switch. Keep this workaround in next.config instead.
When can you remove this?
Treat it as a temporary split between two build targets. I would remove it only when:
A Next.js release or merged fix mentions adapters and standalone together.
The lockfile has the exact version you tested.
A Vercel preview gets through onBuildComplete.
The non-Vercel build still creates a working standalone server, if you need one.
As of August 7, 2026, issue #96646 is still open. For now, the target-aware config is the least weird option. If you can't use it, 16.2.11 is the boring fallback.
Sources and further reading
- Next.js issue #96646 · Next.js GitHub
- Turbopack adapter trace change #93684 · Next.js GitHub
- Next.js output configuration · Next.js documentation
- Vercel system environment variables · Vercel documentation