Demo, all content is generated
Question

Users get 'Failed to find Server Action' right after every deploy

Solved · 419 views · asked by max_ships_it · edited

Every time I push, a few users report that the "Save" button on the settings page does nothing. In the Vercel logs I see:

Error: Failed to find Server Action "7f3a...". This request might be from an older or newer deployment.

It goes away when they refresh. I deploy 3-4 times a day right now, so this happens a lot. Claude Code says it is "a caching issue" and wants to add export const dynamic = 'force-dynamic' everywhere, which feels wrong.

What I’ve tried

Added force-dynamic on the settings page as Claude suggested. No change, the error still shows after each deploy.

Comment
Which Next version? Skew handling improved a lot over the last releases. kenji_w · edited

3 answers

Marked as helpful by the asker
rafa_dev · edited

Not a caching issue. Server Action IDs change with every build. A user who loaded the page before your deploy still has the old JavaScript in their tab, clicks Save, and sends an action ID the new deployment has never heard of.

Options, in order of effort:

  1. Skew Protection (Vercel project settings, Advanced). Vercel keeps routing requests from an old client to the deployment it came from for a while. Available on Pro. This is the real fix.
  2. Catch it on the client and reload:
try {
  await saveSettings(formData);
} catch (e) {
  if (String(e).includes("Failed to find Server Action")) window.location.reload();
}
  1. Deploy less often during the day. Not a fix, but 3-4 deploys with active users means you hit the window constantly.

Remove the force-dynamic again, it only costs you performance.

Comment
I'm on Pro, turned on Skew Protection, deployed twice with a tab open and Save still worked. Thanks! max_ships_it · edited
If you ever self-host: set NEXT_SERVER_ACTIONS_ENCRYPTION_KEY to the same value on every build and every instance, otherwise you get this even without deploys. kenji_w · edited
sofia_gr · edited

Also worth knowing: bots replaying old POST requests trigger the same log line. If you see it hours after a deploy with no user complaints, it is probably noise.

Comment
arjun_codes · edited

Separate from the deploy issue: the button "doing nothing" means the error isn't surfaced. Use useActionState (or at least a try/catch around the call) so users see "something went wrong, refresh" instead of a dead button.

Comment
good point, it failed completely silently. adding that too max_ships_it · edited