Lire une stack trace
Exploiter une stack trace pour localiser l’origine d’un plantage.
Objectifs
À la fin de cette leçon, vous saurez :
- décoder la structure d'une stack trace Node ;
- identifier fichier, ligne, fonction et origine du plantage ;
- distinguer l'endroit du crash de la cause du crash.
🔗 Pour vous rafraîchir la mémoire : les trois familles d'erreurs
Fabriquons volontairement un plantage
Créez plante.js :
function calculerMoyenne(notes) {
const total = notes.reduce((somme, n) => somme + n, 0);
return total / notes.length;
}
function traiterClasse(classe) {
return calculerMoyenne(classe.notes);
}
traiterClasse({ eleve: "Paul" });
Exécution :
node plante.js
Résultat :
C:\...\plante.js:8
const total = notes.reduce((somme, n) => somme + n, 0);
^
TypeError: Cannot read properties of undefined (reading 'reduce')
at calculerMoyenne (C:\...\plante.js:2:23)
at traiterClasse (C:\...\plante.js:5:10)
at Object.<anonymous> (C:\...\plante.js:7:1)
...
Anatomie d'une stack trace
Trois blocs à distinguer :
1. La ligne fautive, reproduite avec son curseur :
const total = notes.reduce(...)
^
2. Le type et le message : TypeError + « Cannot read properties of undefined (reading 'reduce') ». Traduction : on a tenté d'appeler .reduce sur undefined.
3. La pile d'appels (stack), de haut en bas :
at calculerMoyenne (...) ← là où le crash a eu lieu
at traiterClasse (...) ← qui appelait calculerMoyenne
at Object.<anonymous> ← le niveau racine du fichier
La pile se lit comme une pile d'assiettes : le haut est le dernier geste posé (le crash), chaque niveau en dessous est qui a demandé ce geste.
Le réflexe complet
- Lire le type (
TypeError) : famille de problème. - Lire le message en entier : quelle propriété, sur quelle valeur.
- Regarder la première ligne de la pile : où ça a cassé.
- Remonter les lignes suivantes : par quoi ça a été déclenché.
- Se poser LA question : pourquoi cette valeur vaut-elle
undefinedici ?
Crash ≠ cause
Dans notre exemple, le crash a lieu dans calculerMoyenne, mais la cause est ailleurs : traiterClasse a transmis un objet sans propriété notes. Corriger la ligne 2 ne servirait à rien ; il faut soit transmettre les bonnes données, soit défendre l'accès :
if (!classe.notes) {
throw new Error("Classe sans notes : " + classe.eleve);
}
Message clair + plantage immédiat au bon endroit valent mieux qu'un comportement silencieux faux.
Les colonnes ligne:colonne
Chaque référence est fichier:ligne:colonne. Dans plante.js:2:23, la colonne pointe précisément l'expression .reduce. Avec des éditeurs modernes, Ctrl+clic sur ces références ouvre directement l'emplacement.
Erreurs chaînées
Une erreur peut en cacher une autre : la trace se termine parfois par Caused by: — lisez alors les deux piles, celle de l'erreur finale ET celle de sa cause première.
Exercice
Analysez cette trace sans exécuter quoi que ce soit :
TypeError: Cannot read properties of undefined (reading 'push')
at ajouterTache (C:\proj\todo.js:12:9)
at gererJournee (C:\proj\agenda.js:40:3)
at main (C:\proj\index.js:5:5)
- Quel type d'erreur ? Que signifie-t-il ?
- Quelle ligne planterait à coup sûr si on y allait ?
- Qui a appelé la fonction fautrice ?
- Proposez deux hypothèses de cause possibles.
- Pourquoi corriger la ligne 12 de todo.js ne suffirait probablement pas ?
Résumé
- Stack trace = message + pile d'appels ; on lit le haut pour le lieu, le bas pour le contexte.
fichier:ligne:colonnelocalise exactement l'expression fautive.- L'endroit du crash n'est pas toujours la cause : remonter la pile.
- Un plantage précoce avec message explicite vaut mieux qu'un silence trompeur.
Correction disponibleCherchez d’abord par vous-même.Voir la correction
Correction
Réponses détaillées
1. TypeError : tentative d'appeler la méthode .push sur undefined. Autrement dit, la variable sur laquelle ajouterTache fait son push n'est pas le tableau attendu.
2. La ligne 12 de todo.js, colonne 9 : c'est l'emplacement exact signalé par la trace.
3. gererJournee, définie dans agenda.js ligne 40, elle-même appelée depuis main (index.js ligne 5).
4. Deux hypothèses plausibles :
gererJourneea passéundefined(propriété absente d'un objet, paramètre oublié) ;ajouterTacheattend un tableau mais reçoit autre chose (résultat d'une fonction renvoyantundefinedsur un cas non géré, typiquement une recherche sans résultat).
5. Parce que la fonction fait correctement son travail quand on lui donne un tableau : le vrai bug est en amont — la donnée transmise. Corriger en amont (valider l'entrée, garantir la donnée) supprime le problème pour tous les futurs appelants ; maquiller la ligne 12 le masquerait seulement ici.