Aller au contenu

TrainHub — Erreurs courantes

Documentation initiale

Cette page a été rédigée lors de la transmission du projet à l'org EPITECH (à partir de la lecture du code, pas d'un historique d'incidents en production). Elle liste les points de fragilité connus par construction ; à compléter au fil des vrais incidents rencontrés.

Exécution de code (Judge0)

Déprécié — repris par devkora (Zeno)

Le backend Judge0/Piston décrit ci-dessous est déprécié. La sandbox d'exécution de code est reprise par Edwin dans un module nommé devkora, côté projet Zeno. Cette section reste utile pour comprendre l'ancien fonctionnement et le code encore présent dans lib/compiler/, mais pour un incident en cours, vérifier d'abord si devkora est déjà en place avant de suivre ces étapes.

/api/compile ou /api/recode/auto-submit timeout / échoue silencieusement

Symptôme : la compilation ne renvoie jamais de résultat, ou échoue après un délai anormalement long.

Cause probable : JUDGE0_API_URL n'est pas configuré (ou mal configuré) en production. Le code par défaut pointe sur http://localhost:2358 (lib/compiler/judge0.ts) — une instance qui n'existe que sur une machine de dev locale. En prod, Judge0 doit être hébergé séparément (VPS, conteneur dédié à partir de judge0/docker-compose.yml) et son URL réelle passée via JUDGE0_API_URL.

Solution :

  1. Vérifier la variable sur Vercel : vercel env ls (ou dashboard Vercel → Settings → Environment Variables).
  2. Vérifier que l'instance Judge0 répond :
    curl -s -H "X-Auth-Token: $JUDGE0_API_KEY" "$JUDGE0_API_URL/languages"
    
  3. Si l'instance auto-hébergée est down, la relancer (docker compose -f judge0/docker-compose.yml up -d sur la machine qui l'héberge) ou basculer temporairement sur Piston (COMPILER_BACKEND=piston + PISTON_API_URL).

Le mauvais compilateur est utilisé (Clang au lieu de GCC ou inversement)

Symptôme : un exercice qui utilise des flags spécifiques à GCC (-std=gnu*) échoue à la compilation ou se comporte différemment de ce qui est attendu.

Cause : lib/compiler/judge0.ts choisit automatiquement le language_id — Clang (75) par défaut, GCC (50) uniquement si les flags de compilation contiennent -std=gnu. Un exercice qui a besoin de GCC pour une autre raison (extension GNU sans ce flag précis) tombera quand même sur Clang.

Solution : vérifier les flags de compilation configurés sur la question/l'exercice concerné ; ajouter -std=gnu99 (ou équivalent) explicitement si le comportement GCC est requis.


Cron (rappels d'entraînement)

Le cron training-reminders ne s'exécute pas / renvoie 500

Symptôme : GET/POST /api/cron/training-reminders renvoie 500, ou les étudiants ne reçoivent jamais de rappel.

Cause : la route est fail-closed — si CRON_SECRET n'est pas configuré sur Vercel, elle refuse volontairement de s'exécuter plutôt que de tourner sans protection (n'importe qui pourrait sinon déclencher un envoi massif d'emails en appelant l'URL directement).

Solution :

  1. Vérifier que CRON_SECRET est bien défini dans les variables d'environnement Vercel (Production).
  2. Vérifier que le cron Vercel appelle bien la route avec le header attendu (Vercel Cron ajoute automatiquement Authorization: Bearer $CRON_SECRET si la variable est configurée côté projet).
  3. Tester manuellement (en gardant le secret privé) :
    curl -s -o /dev/null -w "%{http_code}\n" \
      -H "Authorization: Bearer $CRON_SECRET" \
      https://<domaine-prod>/api/cron/training-reminders
    

Les emails de rappel n'arrivent pas alors que le cron répond 200

Cause probable : RESEND_API_KEY invalide/expirée, ou rate limit Resend dépassé (l'envoi est fait par lot avec un délai de 100ms entre lots pour respecter les limites, mais un volume anormalement élevé peut quand même buter dessus).

Solution : vérifier le dashboard Resend (logs de livraison, erreurs de quota) et la validité de la clé API.


Import CSV (étudiants / groupes)

Import qui échoue silencieusement sur certaines lignes

Cause probable (par analogie avec des plateformes similaires du même auteur) : une ligne avec un champ obligatoire vide, ou un CSV dont l'en-tête ne correspond pas exactement à ce qui est attendu par app/api/admin/import-students ou app/api/admin/groups/import-csv.

Solution : relire le composant components/student/student-import.tsx (ou équivalent groupes) pour la liste exacte des colonnes attendues, et vérifier l'en-tête du CSV importé caractère pour caractère (espaces, accents).


Build / TypeScript

Une régression de types passe en production sans bloquer le déploiement

Cause : next.config.mjs a typescript.ignoreBuildErrors: true — le build Vercel réussit même si tsc remonterait des erreurs. C'est un choix assumé du projet (vitesse d'itération), pas un oubli, mais ça veut dire qu'il faut lancer tsc (ou pnpm build en observant les warnings, ou un pnpm exec tsc --noEmit séparé) manuellement pour attraper ces régressions avant qu'elles n'atteignent la prod.


Qualité des questions (banque de contenu)

Un étudiant sélectionne la bonne réponse mais elle est comptée invalide

Symptôme : remonté par des étudiants du C-Pool d'Abidjan — sur certaines questions, la réponse qui semble correcte (et l'est, pédagogiquement) est refusée par le correcteur automatique.

Cause : pas un bug applicatif — certaines questions de la table questions sont mal rédigées ou ont une réponse correcte mal renseignée (énoncé ambigu, plusieurs réponses valides mais une seule marquée correcte, coquille dans le code_snippet ou les options d'un QCM, etc.). Le moteur de correction fait exactement ce qu'on lui demande ; c'est la donnée qui est en cause.

Solution :

  1. Identifier la question précise remontée par l'étudiant (catégorie + énoncé) et la relire dans l'admin (app/admin/questions), avec le composant de prévisualisation/test (test-question-dialog.tsx) pour rejouer la question comme un étudiant.
  2. Corriger l'énoncé, les options ou la réponse correcte directement dans l'admin.
  3. Pas de vérification automatisée de cohérence des questions à ce jour — c'est un défaut connu du contenu, à corriger au cas par cas au fil des retours étudiants plutôt qu'une régression à traquer dans le code.

Recueillir les retours

Garder une trace des questions signalées (catégorie + id) au fil de l'eau permettrait à terme de prioriser une relecture de la banque de questions plutôt que de découvrir les cas un par un via les retours étudiants.


Migration self-managed (résidus)

Des fichiers lib/db/, drizzle.config.ts ou infra/ réapparaissent

Cause : une tentative de migration vers un backend Postgres auto-hébergé + Drizzle a existé sur une branche (migration/self-managed), puis a été entièrement annulée. Si ces artefacts réapparaissent (rebase malheureux, branche relancée par erreur), ce n'est pas une intention produit actuelle.

Solution : vérifier avec l'historique git (git log --all --oneline -- lib/db drizzle.config.ts infra/) avant de les garder — la décision documentée est de rester 100% Supabase (voir overview.md).