Exceptions, propagation et logs
Métier vs technique, cause préservée, réponse unique.
Objectifs
À la fin de cette leçon, vous saurez :
- distinguer erreurs métier et techniques ;
- propager sans avaler ni doubler les traitements ;
- répondre « où, quoi, pourquoi, dans quel contexte » quand ça casse.
🔗 Pour vous rafraîchir la mémoire : Pool pg et requêtes paramétrées ($1, $2) · méthodes HTTP et codes de statut · la méthode de débogage en six étapes
Deux familles d'erreurs
// Erreur MÉTIER : prévue, porte un message pour l'utilisateur
throw new NotFoundException('Tâche inconnue'); // → 404
throw new ConflictException('Email déjà utilisé'); // → 409
// Erreur TECHNIQUE : imprévue, à investiguer
pool.query(...) // base injoignable, bug de code...
La traduction NestJS que vous connaissez : les HttpExceptions sortent en codes propres via le filter ; les techniques tombent en 500 + log détaillé. Règle de contenu : message métier pour l'utilisateur, détails techniques pour les LOGS — jamais l'inverse (ne pas exposer la stack trace au client).
Propager : ne rien avaler
// ❌ Avale : l'erreur devient invisible
try { await sauvegarder(); } catch { return null; }
// ❌ Double traitement : loggé ici ET dans le filter
try { await sauvegarder(); } catch (e) {
logger.error(e);
throw new Error("Échec"); // la trace originale est perdue !
}
// ✅ Journaliser OU propager, rarement les deux
try { await sauvegarder(); }
catch (e) {
throw new Error("Sauvegarde impossible", { cause: e }); // cause préservée
}
Le pattern honnête : chaque couche ajoute du CONTEXTE (cause), une seule couche décide de la réponse. Les erreurs chaînées de Node (cause) permettent de remonter toute la pile.
Les quatre questions d'un bon log
Quand logger.error se déclenche, il doit répondre :
OÙ : fichier/service/méthode (souvent implicite dans le contexte)
QUOI : le message précis ("INSERT tasks a échoué")
POURQUOI: la cause ("contrainte FK violée sur user_id=99")
CONTEXTE: les données utiles ("req POST /tasks, user=7, body={...}")
Un log qui manque d'une des quatre réponses force à rejouer le problème : c'est lui qu'on corrige d'abord.
Exercice
- Classez : "email invalide", "ECONNREFUSED 5432", "slug dupliqué", "TypeError undefined".
- Corrigez ce catch qui perd tout :
catch(e){ console.log(e); }. - Dans Devmind, retrouvez où les erreurs métier deviennent des réponses HTTP.
Résumé
- Métier = réponse propre ; technique = 500 + investigation.
- Contexte ajouté couche par couche ; décision unique de réponse.
- Un log complet économise une heure de débogage.
Correction disponibleCherchez d’abord par vous-même.Voir la correction
Correction
Réponses détaillées
Question 1. Métier : email invalide (400), slug dupliqué (409). Techniques : ECONNREFUSED et TypeError (500 + alerte). Le classement détermine qui voit quoi : utilisateur vs développeur.
Question 2.
catch (e) {
logger.error({ err: e, userId }, 'sauvegarde échouée');
throw new ConflictException('Enregistrement impossible');
}