Next.js error
Invalid Server Action Payload: Failed to Decrypt
The error
Invalid Server Action payload: failed to decrypt.A browser holding one deployment's JavaScript called a server running a different one. The encryption key changed between builds, so the arguments no longer open.
Invalid Server Action payload: failed to decrypt.
Server Action arguments are encrypted by the build that produced the page and decrypted by the server that receives them. When those are different builds, the decryption fails and the server refuses the call.
It is not a bug in the action. It is two deployments talking past each other.
Why it clusters after a deploy
The browser already has the old build's JavaScript. A deploy replaces the server. The user, who has been on the page for twenty minutes writing something into a form, presses submit - and sends a payload sealed with a key the new server does not have.
The symptom is a short burst of failures starting the minute a deploy completes and fading as sessions turn over. If your error reporting groups by time, it looks like the deploy broke something. It did, for everybody who was mid-task.
Pin the key
By default the encryption key is generated per build, which is what makes every deploy a cutover. Setting it yourself keeps actions working across deploys:
# generate once
openssl rand -base64 32NEXT_SERVER_ACTIONS_ENCRYPTION_KEY=<that value>
Set it in your platform's environment configuration, identically across every instance serving the same application. Then a payload sealed by yesterday's build still opens today.
Two things to be careful about. It is a secret with real power - anything holding it can construct a payload your server will accept - so it belongs in a secret store and not in the repository. And rotating it has the same effect as not pinning it at all, for the length of one session turnover, so rotate deliberately rather than on a schedule nobody remembers setting.
What pinning does not fix
The key covers the arguments. It does not make an old client compatible with a new server in general.
If a deploy changes what an action expects - a renamed field, a new required argument, an action that no longer exists - then an old page can still reach a new server with arguments that decrypt perfectly and mean the wrong thing. That failure is quieter and worse than this one.
So treat a Server Action signature the way you would treat an API endpoint during a rolling deploy. Add before removing, accept the old shape for a release, and drop it once nothing is sending it. The encryption key keeps the envelope readable; keeping the contents meaningful is still your problem.
The other reason to see it
A payload that was never produced by any of your builds also fails to decrypt, and that is the check doing its job.
Burst after each deploy is skew. A steady trickle that does not correlate with deploys is somebody posting to your action endpoints directly, which is worth knowing about and is not fixed by an environment variable.
Deployment skew is one of the failure modes that only exists in production and only for a few minutes at a time, which is what makes it easy to dismiss and hard to reproduce. It is the kind of thing a support engagement is for.
