Fixing "Failed to find Server Action" after deploys

· 2 min read

After every deploy, our production logs showed the same Next.js error: Failed to find Server Action. There was no known way to reproduce it. Two settings fixed it: a fixed encryption key and a build ID taken from the git hash.

The cause

Next.js encrypts Server Actions with a key, and by default every build generates its own key. Each action also gets an ID that is part of the build.

So when two builds are live at the same time, they disagree. A request made against one build reaches a server running another build, and that server can't find the action. You get Failed to find Server Action.

That is why it only showed up after deploys. During a deploy, the old build and the new build overlap.

Reproducing it

I couldn't fix something I couldn't see, so the first job was to make it happen on my machine.

I hadn't used Docker before this, so I learned it for this task. I wrote a Dockerfile and a Docker Compose file and ran 2 images of the app side by side, the same way two builds overlap during a deploy. With that setup I reproduced the error step by step.

Now I had a test: if the fix worked, the same steps would stop failing.

The fix

First, set the encryption key yourself so every build uses the same one. Next.js reads it from an environment variable at build time:

NEXT_SERVER_ACTIONS_ENCRYPTION_KEY=your-base64-key next build

The key has to be base64 with a valid AES length (16, 24 or 32 bytes). Keep it in your secrets, not in the repo.

Second, give the build a stable ID instead of a random one. I used the git hash, so two builds of the same commit get the same ID:

// next.config.js
module.exports = {
  generateBuildId: async () => process.env.GIT_HASH,
};

The Docker test stopped failing. Then I repeated the same reproduce-and-fix steps on the main project.

The result

The error no longer appears in the production logs after deploys. I applied the same fix to 2 projects.

If your Next.js app runs more than one server, or old and new builds overlap during deploys, set both of these before you see the error.