Fait partie de Hébergement par cadricielNext.js · Dépannage

Corriger « Failed to find Server Action » après un déploiement Next.js.

Le navigateur appelle une Server Action avec un identifiant que le serveur ne connaît pas. Next.js génère de nouveaux identifiants à chaque compilation : une page chargée avant le déploiement, un deuxième serveur sur une autre compilation, une clé de chiffrement différente ou du HTML en cache suffisent. Définissez deploymentId, une seule compilation par version, et rechargez les onglets périmés.

Faits vérifiés le

Ce que l’erreur veut dire

Quand un composant client appelle une Server Action, le navigateur envoie un POST avec un en-tête Next-Action qui contient l’identifiant de l’action. Le serveur cherche cet identifiant dans la compilation qu’il exécute. S’il ne le trouve pas, il journalise Error: Failed to find Server Action "7f3a…". This request might be from an older or newer deployment. et répond par un 404. Dans la console du navigateur, le même échec se lit Server Action "7f3a…" was not found on the server.

Next.js rend ces identifiants non déterministes à dessein, pour la sécurité, et ils peuvent changer d’une compilation à l’autre. L’erreur veut donc presque toujours dire que la page dans le navigateur et le serveur qui lui répond viennent de compilations différentes.

Un second message, Server Reference ID did not match the expected format, est autre chose : l’identifiant n’a même pas la forme de ceux que produit cette version de Next.js. La documentation de Next.js donne deux causes : un client et un serveur sur des versions de Next.js aux formats différents, ou des requêtes malformées, comme celles des scanneurs de sécurité. S’il arrive en rafale depuis une seule adresse IP, c’est sans doute un scanneur, et vous pouvez l’ignorer.

Les causes, et la correction de chacune

Parcourez le tableau de haut en bas. La première ligne est celle que presque tout le monde rencontre, parce qu’elle se produit à chaque déploiement, chez n’importe quel hébergeur.

CauseComment la reconnaîtreCorrectionSur Canner
Un onglet ouvert avant le déploiement † †Les erreurs se regroupent dans les minutes qui suivent chaque déploiement, puis cessentDéfinir deploymentId pour qu’un onglet périmé se recharge au lieu d’envoyer d’anciens identifiants; intercepter l’échec côté clientSe produit : un seul processus sert la production, les vieux onglets tombent donc sur la nouvelle compilation. CANNER_DEPLOYMENT_ID est défini à chaque compilation
Deux serveurs sur des compilations différentes † †Erreurs au hasard, à toute heure, à peu près au prorata du trafic de chaque serveurExécuter la même sortie de compilation partout; compiler une fois et livrer cet artefactNe s’applique pas : un processus par projet, remplacé à chaque déploiement
Clés de chiffrement différentes †Plusieurs instances compilées séparément; les actions avec arguments liés ou fermetures échouentDéfinir la même NEXT_SERVER_ACTIONS_ENCRYPTION_KEY à la compilation pour toutes les instancesInutile avec un seul processus; à définir si vous faites aussi tourner des copies ailleurs
HTML en cache d’une compilation antérieure †Les erreurs persistent longtemps après le déploiement, seulement sur les pages mises en cacheVider le CDN au déploiement, ou ne pas mettre en cache le HTML qui contient des formulairesLe cache de réponses de Canner est vidé à chaque déploiement de production réussi; un CDN externe, c’est à vous de le vider
Requêtes malformées ou de scanneurs †did not match the expected format, souvent d’une seule IP qui essaie beaucoup d’URLRien à corriger dans l’appli; limitez ou bloquez la source si elle fait du bruitApparaît dans les journaux de l’appli comme toute autre requête

† Les détails sur les concurrents proviennent des pages publiées par chaque fournisseur aux dates indiquées; les prix et forfaits changent, vérifiez auprès du fournisseur avant de décider. Un onglet ouvert avant le déploiement (2026-10-29) · Un onglet ouvert avant le déploiement (2026-10-29) · Deux serveurs sur des compilations différentes (2026-10-29) · Deux serveurs sur des compilations différentes (2026-10-29) · Clés de chiffrement différentes (2026-10-29) · HTML en cache d’une compilation antérieure (2026-10-29) · Requêtes malformées ou de scanneurs (2026-10-29)

Onglets périmés : définir un identifiant de déploiement

Quelqu’un ouvre votre formulaire à 10 h. Vous déployez à 10 h 05. À 10 h 07, il clique sur Enregistrer. Son onglet exécute encore le JavaScript de 10 h, qui envoie l’identifiant d’action de 10 h à un serveur qui exécute la compilation de 10 h 05. C’est tout le bogue, et aucun hébergeur ne peut le faire disparaître complètement à moins de garder l’ancienne compilation en marche à côté de la nouvelle.

Next.js a un réglage pour ça. Avec `deploymentId`, les navigations côté client envoient un en-tête x-deployment-id, le serveur répond avec le sien et, s’ils diffèrent, le client recharge la page au complet au lieu de naviguer côté client. L’utilisateur arrive sur la nouvelle compilation et ses nouveaux identifiants. Toute valeur qui change à chaque déploiement fait l’affaire :

// next.config.ts
import type { NextConfig } from "next";

const nextConfig: NextConfig = {
  // Any value that changes on every deploy. Canner sets CANNER_DEPLOYMENT_ID
  // during each build; elsewhere use your git SHA or CI build number.
  deploymentId: process.env.CANNER_DEPLOYMENT_ID,
};

export default nextConfig;

Intercepter l’échec côté client

L’identifiant de déploiement agit à la navigation suivante. Un utilisateur qui reste sur une page et clique sur un bouton peut encore envoyer un appel périmé. Quand l’action est introuvable, la promesse attendue par le client est rejetée avec une erreur que reconnaît unstable_isUnrecognizedActionError, de next/navigation (dans Next.js 16.2; le préfixe unstable_ veut dire que la fonction peut changer). Gérez ce cas au lieu de laisser un bouton mort :

"use client";
import { unstable_isUnrecognizedActionError } from "next/navigation";
import { saveDraft } from "./actions";

export function SaveButton({ id }: { id: string }) {
  async function onClick() {
    try {
      await saveDraft(id);
    } catch (err) {
      // This tab was loaded before the last deploy.
      if (unstable_isUnrecognizedActionError(err)) {
        if (confirm("This page was updated. Reload to continue?")) location.reload();
        return;
      }
      throw err;
    }
  }
  return <button onClick={onClick}>Save</button>;
}

NEXT_SERVER_ACTIONS_ENCRYPTION_KEY

Next.js chiffre les variables qu’une Server Action capture avant de les envoyer au navigateur. Par défaut, chaque compilation crée sa propre clé. Quand plusieurs instances servent le même site, une action chiffrée par l’une ne peut pas être déchiffrée par une autre, et Next.js le signale comme « Failed to find Server Action ».

La correction du guide d’auto-hébergement est une clé commune : en base64, de 16, 24 ou 32 octets. Elle est lue à la compilation et intégrée à la sortie : la définir seulement sur le serveur en marche ne sert à rien.

  • Sur Canner, ajoutez-la sous l’onglet Variables d’environnement du projet avec la portée production ou toutes, et marquez-la sensible. Une variable à portée exécution seulement n’atteint jamais la compilation : la clé ne serait pas intégrée. Voir les portées.
  • Une clé commune ne rend pas les identifiants d’action stables entre deux compilations différentes. Elle règle le déchiffrement entre instances, pas les onglets périmés.
# Generate once, keep it in your secrets store
openssl rand -base64 32

# It must be present when `next build` runs
NEXT_SERVER_ACTIONS_ENCRYPTION_KEY=<the 44-character value> next build

Ce que fait Canner au basculement

Canner exécute chaque projet comme un seul processus next start de longue durée (déroulement d’un déploiement). Un déploiement de production compile la nouvelle version, exécute votre commande de mise en production s’il y en a une, puis démarre la nouvelle compilation à la place de l’ancienne. Elle prend le trafic dès qu’elle répond à la vérification d’état. Deux compilations ne répondent jamais en même temps en production : les causes liées à plusieurs instances ne peuvent donc pas se produire.

Les onglets périmés, si. Canner ne garde pas l’ancienne compilation en marche pour les vieux onglets, comme le fait la Skew Protection de Vercel : définissez deploymentId et gérez l’appel rejeté comme ci-dessus. Chaque aperçu de demande de tirage est une compilation distincte, à sa propre adresse, et ne se mélange pas à la production.

Deux autres choses changent la compilation sous les pieds de vos utilisateurs : le retour arrière automatique recompile votre dernier bon commit, et un retour arrière manuel en recompile un plus ancien. Ce sont de nouvelles compilations avec de nouveaux identifiants d’action : traitez-les comme n’importe quel déploiement.

Questions

Pourquoi « Failed to find Server Action » n’arrive-t-il qu’en production?

En développement, il y a un seul serveur, qui recompile à chaque modification : la page et le serveur concordent toujours. En production, un navigateur peut garder ouverte pendant des heures une page de la compilation précédente. Le déploiement suivant change les identifiants d’action sous elle.

Ai-je besoin de NEXT_SERVER_ACTIONS_ENCRYPTION_KEY?

Seulement si plusieurs serveurs répondent pour le même site et doivent déchiffrer les actions les uns des autres. Définissez-la avant next build, puisque la clé est intégrée à la sortie de compilation. Elle ne règle pas les onglets restés ouverts pendant un déploiement; deploymentId, oui.

Peut-on garder les mêmes identifiants de Server Action d’une compilation à l’autre?

Pas de façon fiable. Next.js documente ces identifiants comme non déterministes et précise qu’ils peuvent changer entre les compilations. Prévoyez plutôt les vieux onglets : un identifiant de déploiement pour forcer le rechargement, et un catch autour de l’appel.

Canner garde-t-il l’ancienne version en marche pendant un déploiement?

Non. Un seul processus sert la production, et un déploiement le remplace dès que la nouvelle compilation passe la vérification d’état. Voir compilations et retours en arrière.

Déployez votre appli Next.js à Montréal.

Un seul processus next start, une base de données à côté, et vos données au Québec. Déployez depuis GitHub ou avec le CLI.