Menu

Déboguer avec l'IA : trouver la cause d'un bug

Pour déboguer avec ChatGPT ou Claude, collez l'erreur complète et le code qui l'a levée, dites ce que vous attendiez et ce qui s'est passé, listez ce que vous avez déjà essayé, et demandez la cause avant la correction.

Chaque prompt de cette page se modifie, puis s'ouvre dans ChatGPT, Claude ou une autre application d'IA.

Déboguer avec l'IA marche le mieux quand vous donnez au modèle ce que vous donneriez à un collègue assis à côté de vous : l'erreur entière, le code qui l'a levée, ce que vous attendiez, ce qui s'est passé à la place et ce que vous avez déjà écarté. Le modèle ne peut ni exécuter votre programme ni voir vos données : tout ce qu'il sait du bug vient de ce que vous collez. L'habitude la plus utile est de demander la cause avant la correction.

Tout coller, pas seulement l'erreur

Les deux onglets ci-dessous décrivent le même bug. Un script lit un fichier CSV exporté depuis Excel et plante avec KeyError: 'email', alors que le fichier a bien une colonne email.

Corrige ça : KeyError: 'email'
Try it
Example replyReplies vary between models and runs.

Une KeyError signifie que le dictionnaire n'a pas de clé 'email'. Vous pouvez éviter l'erreur avec .get(), qui renvoie None au lieu de lever une exception :

email = row.get("email")

Ou vérifiez d'abord :

if "email" in row:
    email = row["email"]

La première réponse a raison sur ce qu'est une KeyError, et son conseil est ici nuisible. Avec row.get("email"), le plantage disparaît et chaque e-mail devient None. Le modèle a répondu à la version la plus courante de l'erreur, parce que c'est tout ce que le prompt décrivait.

Le rapport complet a marché grâce à deux lignes. "Seule la première colonne échoue" et "enregistré depuis Excel au format CSV UTF-8" sont les indices qui mènent au BOM, et aucun ne figure dans le message d'erreur. Vous savez rarement lequel de vos détails est l'indice, c'est pourquoi vous les collez tous.

Les cinq choses à inclure

  1. L'erreur complète. Toute la traceback ou la sortie de la console, pas une paraphrase. Les numéros de ligne et la chaîne d'appels montrent où l'échec a commencé, souvent quelques niveaux avant l'endroit où il est apparu.
  2. Le code qui l'a levée. La fonction qui échoue et le code qui l'appelle. Si l'erreur mentionne une ligne, vérifiez que cette ligne figure dans ce que vous collez.
  3. L'attendu et l'observé. Une phrase chacun. Pour les bugs sans erreur du tout (mauvaise sortie, page blanche, requête lente), c'est tout le rapport de bug.
  4. Votre environnement. Version du langage, système d'exploitation, versions du framework et des bibliothèques quand elles peuvent compter. Les bugs d'encodage, de chemins et de dates dépendent souvent de la plateforme.
  5. Ce que vous avez déjà essayé. Cela évite que le modèle le propose à nouveau, et le résultat de chaque tentative est une preuve. "Retirer la partie email fait marcher le script" a réduit le bug CSV à une seule colonne.

Demander la cause avant la correction

Une demande de correction pousse le modèle à modifier le code jusqu'à ce que l'erreur disparaisse. Une demande de cause lui demande de raisonner sur l'origine de l'erreur, et la correction en découle. Demandez une courte liste de causes classées avec un moyen de vérifier chacune, puis faites vous-même les vérifications. Ce modèle de prompt fait exactement cela :

Classer les causes, pas encore de correction
Fill in
Parts
Aide-moi à trouver la cause d'un bug dans mon code JavaScript. N'écris pas encore de correction.
Attendu : la liste des utilisateurs s'affiche au chargement de la page Observé : page blanche, et cette erreur dans la console du navigateur
TypeError: Cannot read properties of undefined (reading 'map')function UserList() { const [users, setUsers] = useState(); useEffect(() => { fetch("/api/users") .then((res) => res.json()) .then((data) => setUsers(data)); }, []); return ( <ul> {users.map((u) => ( <li key={u.id}>{u.name}</li> ))} </ul> ); }
Liste jusqu'à trois causes probables, la plus probable en premier. Pour chacune, donne une vérification d'une ligne que je peux lancer pour la confirmer ou l'écarter.
Try it
Example replyReplies vary between models and runs.
  1. Le composant s'affiche avant que les données existent. useState() démarre à undefined, et React rend le composant une première fois avant que l'effet s'exécute, donc users.map est appelé sur undefined. Cela suffit à produire exactement ton erreur, à chaque chargement. Vérification : ajoute console.log(users) juste avant le return. S'il affiche undefined et que l'erreur suit aussitôt, c'est ça.
  2. L'API renvoie autre chose qu'un tableau. Si elle renvoyait un objet comme { users: [...] }, l'erreur serait différente (users.map is not a function), ce n'est donc pas l'erreur que tu as collée. Ce peut quand même être le problème suivant une fois la cause 1 réglée. Vérification : console.log(data) dans le second .then.
  3. La requête échoue. Pas encore en jeu : comme le premier rendu lève une erreur, React n'exécute jamais l'effet, donc la requête n'est même pas envoyée. Vérification : l'onglet Réseau ne montre aucune requête /api/users, ce qui confirme aussi la cause 1.

La réponse fait quelque chose qu'une réponse centrée sur la correction saute : elle écarte des causes parce que l'erreur qu'elles produiraient diffère de celle que vous avez collée, ou parce que le code ne va jamais assez loin pour qu'elles se produisent. C'est aussi pourquoi le texte exact de l'erreur compte. Demander au modèle de lister les causes avant de répondre est une forme légère de chain of thought : le raisonnement vient d'abord et la conclusion s'appuie dessus.

Construire une reproduction minimale

Une reproduction minimale est le plus petit programme qui montre encore le bug : des données écrites en dur au lieu d'un appel à la base, une fonction au lieu de tout le module. En construire une trouve souvent le bug avant même de demander à qui que ce soit, car chaque élément retiré soit garde le bug (il n'était pas en cause), soit le fait disparaître (il l'était). Quand ce n'est pas le cas, la reproduction est le prompt idéal : assez courte pour que le modèle lise chaque ligne, et débarrassée du code sans rapport qui pourrait le lancer sur une fausse piste.

Si le bug dépend des données, incluez quelques lignes qui le déclenchent. Un modèle peut raisonner sur [{"id": 1, "name": null}] ; il ne peut pas raisonner sur "certaines lignes en production".

Quand les corrections ne marchent plus

Si la troisième correction du modèle échoue de la même façon, une quatrième demande de correction a peu de chances de faire mieux. Deux choses aident davantage :

  • Donnez-lui de nouvelles preuves. Ajoutez une ligne print ou de log qui montre les vraies valeurs au point d'échec, exécutez, et collez la sortie. Une preuve qui contredit la théorie du modèle est le chemin le plus rapide vers une meilleure théorie.
  • Ouvrez une nouvelle conversation. Les longs fils de débogage se remplissent de théories abandonnées et d'anciennes versions du code, et le modèle peut continuer à construire dessus. Une nouvelle conversation avec le code actuel, l'erreur, les preuves et une ligne "déjà écarté : X et Y" va souvent plus loin en une seule réponse.

Méfiez-vous des réponses assurées sur le comportement d'une bibliothèque. Un modèle peut décrire une option ou une fonction qui n'existe pas ; voir hallucinations de l'IA pour savoir comment vérifier. Quand le code n'est pas cassé mais que vous ne comprenez pas pourquoi il fait ce qu'il fait, un prompt pour expliquer du code est le meilleur outil.

Questions fréquentes

Comment demander à ChatGPT ou Claude de corriger mon code ?

Collez le message d'erreur complet et le code qui l'a levé, puis ajoutez trois lignes courtes : ce que vous attendiez, ce qui s'est passé à la place et ce que vous avez déjà essayé. Demandez la cause la plus probable et comment la confirmer avant de demander une correction. Un simple "corrige ça" obtient la correction de la version la plus courante de l'erreur, qui n'est peut-être pas la vôtre.

Faut-il coller tout mon projet dans l'IA ?

Non. Collez la fonction où l'erreur se produit, le code qui l'appelle et un échantillon des données qu'elle reçoit. Mieux encore, réduisez le problème au plus petit programme qui le reproduit. Les fichiers sans rapport ralentissent la réponse et donnent au modèle plus d'endroits où chercher un problème qui n'y est pas.

Pourquoi la correction de l'IA fait disparaître l'erreur alors que le programme ne marche toujours pas ?

La correction a traité le symptôme. Par exemple, remplacer row["email"] par row.get("email") supprime une KeyError, mais si la clé manque à cause d'un bug en amont, chaque e-mail vaut désormais None en silence. Demander d'abord la cause, et un moyen de la confirmer, évite les corrections qui ne font que masquer le problème.

Et si l'IA continue de proposer des corrections qui ne marchent pas ?

Arrêtez de demander des corrections et donnez-lui plutôt des preuves. Indiquez ce que chaque tentative a changé, ajoutez une ligne print ou de log qui montre les vraies valeurs, et collez cette sortie. Si la conversation est longue, ouvrez-en une nouvelle avec un résumé propre : le code, l'erreur, les preuves et les corrections déjà écartées.

Coddy programming languages illustration

Apprendre à coder avec Coddy

COMMENCER