Erreurs

FougereError représente une erreur métier avec un code typé. Les handlers la lèvent et les couches suivantes conservent son code, son message et ses détails.

throw new FougereError({
  code: ErrorCode.CONFLICT,
  message: `Le slug '${slug}' est déjà pris`,
  entity: 'post',
  operation: 'create',
  // details?: [{ path, message }]   — par champ, utilisé par VALIDATION_FAILED
  // cause?: unknown
});

Les codes

CodeSensProjection HTTP
VALIDATION_FAILEDentrée invalide — details contient les { path, message } par champ400
UNAUTHORIZEDpas d'identité401
FORBIDDENidentité présente, droit absent403
NOT_FOUNDla chose désignée n'existe pas404
CONFLICTl'état refuse la transition (déjà publié, slug pris)409
SERVICE_UNAVAILABLEune Frond distante est injoignable503
INTERNAL_ERRORtout l'inattendu500

INTERNAL_ERROR est le seul dont le message ne sort pas

Les six autres codes ont été écrits pour l'appelant et voyagent entiers. Un INTERNAL_ERROR, non : il peut citer un chemin, une requête ou une ligne, donc il est remplacé par une constante avant de quitter le process.

Il est journalisé au même endroit — masquer et enregistrer vivent dans la même fonction, pour que la phrase existe exactement une fois, sur le serveur. Un opérateur qui cherche « pourquoi ce 500 » la trouve dans les logs avec sa cause, son entité et son opération ; un attaquant ne la voit jamais. Si votre message doit atteindre l'appelant, c'est qu'il ne s'agit pas d'un INTERNAL_ERROR : donnez-lui son code.

Propagation d'une erreur

  1. Le handler lève une FougereError — le même objet que la Frond soit locale ou distante.
  2. Appel local — l'erreur se propage en mémoire, intouchée.
  3. Appel distant — le transport la met en trame JSON-RPC (code: -32000, data: { code, message, entity, operation, details? }) et le côté appelant la reconstruit une FougereError, avec ses details.
  4. Dans une pageuseQuery/useCommand l'exposent comme error (une vraie FougereError) ; useFormFor mappe automatiquement VALIDATION_FAILED.details sur les erreurs par champ.
  5. Sur la surface RESTtoHttpError projette le code vers le vrai statut HTTP (table ci-dessus), la valeur typée entière dans data.

Le navigateur reçoit le même code, le même message et les mêmes erreurs par champ, que la Frond soit locale ou distante. Un hôte inaccessible produit une erreur typée SERVICE_UNAVAILABLE.

Ordre des vérifications

Le blog de ce site effectue les vérifications dans cet ordre :

requireUser(user)        // UNAUTHORIZED
requireOwn(id, user)   // NOT_FOUND, puis FORBIDDEN
→ vérifs d'état          // CONFLICT (déjà publié, brouillon vide)
→ réaliser               // orm.update(…)

Suite : Seeds — initialiser les données par les opérations.

Construit avec Fougere — ce site tourne sur le framework qu'il documente.