Même un bot bien écrit peut mourir en silence à 3 heures du matin ; c'est pourquoi l'uptime d'un bot Discord relève moins du code que de la discipline opérationnelle. Le problème n'est presque jamais que le bot est « mauvais » : c'est que personne ne remarque qu'il a planté et qu'aucun mécanisme ne le relance. Dans ce guide, nous mettons en place, étape par étape, comment détecter pourquoi un bot tombe, comment le faire se rétablir tout seul avec pm2, et comment le surveiller de l'extérieur avec un simple healthcheck.
Pourquoi les bots plantent-ils ?
Connaissez d'abord votre ennemi. L'immense majorité des bots Discord s'arrêtent pour quelques raisons récurrentes :
- Erreurs non capturées : une exception levée dans un gestionnaire d'événement non entouré d'un
try/catchfait tomber tout le processus Node.js. - Rejets de promesse avalés : une promesse sans
awaitni.catch()fait planter le processus sur les versions récentes de Node. - Coupures WebSocket : les microcoupures réseau ou les redémarrages côté Discord cassent la connexion ; discord.js se reconnecte généralement seul, mais reste parfois bloqué dans un état
disconnect. - Fuites mémoire : un cache qui grossit sans cesse ou des
setIntervalnon nettoyés font tuer le processus par OOM (Out Of Memory) en quelques heures. - Rate limits et tokens invalides : si le token est réinitialisé ou qu'un mauvais code déclenche une avalanche de 429, la connexion à la gateway est refusée.
À la lecture de cette liste, la solution devient claire : rendre les erreurs visibles, placer un chien de garde devant le processus, et mesurer de l'extérieur si le bot est réellement « vivant ».
Étape 1 : arrêter d'avaler les erreurs
La première ligne de défense est le code lui-même. Même quand le bot plante, il doit consigner pourquoi il a planté, sinon vous bouclerez éternellement sur la même erreur au fil des redémarrages. Ajoutez des écouteurs au client discord.js et aux événements globaux du processus :
client.on('error', (err) => console.error('[client error]', err));
client.on('shardError', (err) => console.error('[shard error]', err));
process.on('unhandledRejection', (reason) => {
console.error('[unhandledRejection]', reason);
});
process.on('uncaughtException', (err) => {
console.error('[uncaughtException]', err);
process.exit(1); // on quitte volontairement ; pm2 redémarre
});
Il y a ici une décision de conception importante : quand uncaughtException se déclenche, on termine le processus à dessein. Tenter de maintenir le processus en vie après une erreur inconnue, c'est continuer dans un état à moitié cassé. L'approche propre : consigner et quitter, puis laisser la reprise à un gestionnaire de processus.
Étape 2 : redémarrages automatiques avec pm2
pm2 est un gestionnaire de processus qui exécute les applications Node en arrière-plan, les redémarre automatiquement en cas de plantage et collecte leurs logs. Installez-le globalement sur votre VPS :
npm install -g pm2
Vous pouvez démarrer le bot directement, mais conserver la configuration dans un fichier ecosystem.config.js est bien plus propre :
module.exports = {
apps: [{
name: 'discord-bot',
script: './index.js',
instances: 1,
autorestart: true,
max_memory_restart: '300M',
restart_delay: 5000,
max_restarts: 10,
min_uptime: '10s',
env: { NODE_ENV: 'production' }
}]
};
Les champs importants :
- autorestart : lorsque le processus se termine, pm2 le relance.
- max_memory_restart : redémarre le bot de manière proactive si la mémoire dépasse 300 Mo — une assurance contre les fuites.
- restart_delay : attend 5 secondes avant de redémarrer, pour qu'une erreur permanente comme un token invalide ne crée pas une boucle infinie qui sature le CPU.
- min_uptime + max_restarts : si le bot plante 10 fois sans tenir 10 secondes, pm2 le marque « errored » et l'arrête ; cela vous empêche de masquer un vrai problème sous des redémarrages sans fin.
Pour le démarrer et qu'il remonte après un redémarrage du serveur :
pm2 start ecosystem.config.js
pm2 save
pm2 startup # exécutez la commande affichée
Utilisez pm2 logs discord-bot et pm2 status pour suivre les logs et l'état.
Étape 3 : un endpoint de healthcheck
pm2 répond à la question « le processus tourne-t-il ? », mais ne peut pas détecter l'état « le processus est en marche mais la gateway Discord a lâché ». Pour vérifier que le bot est réellement vivant, ajoutez un petit healthcheck HTTP. Le module natif http suffit :
const http = require('http');
http.createServer((req, res) => {
// client.ws.status === 0 -> READY
const healthy = client.isReady() && client.ws.status === 0;
res.writeHead(healthy ? 200 : 503, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
status: healthy ? 'ok' : 'degraded',
ping: client.ws.ping,
uptime: process.uptime()
}));
}).listen(3001);
Désormais, curl http://localhost:3001 affiche l'état de la gateway et le ping du bot. Il est crucial de relier cet endpoint au fait que la gateway soit réellement READY, et pas seulement à process.uptime() — sinon vous prendrez un bot « mort-vivant » pour un bot en bonne santé.
Étape 4 : surveillance externe et alertes
Le dernier maillon, c'est être averti quand quelque chose tourne mal. Reliez l'endpoint de healthcheck à un service de surveillance gratuit (UptimeRobot, Better Stack ou votre propre cron) pour qu'en cas de 503 ou d'absence de réponse, vous receviez une alerte par e-mail/webhook Discord. Une approche d'auto-surveillance simple fonctionne aussi :
setInterval(() => {
if (!client.isReady()) {
console.error('[health] bot pas READY, sortie');
process.exit(1); // laisser pm2 redémarrer proprement
}
}, 60_000);
Si la gateway se bloque en silence, cette boucle fait tomber volontairement le processus pour que pm2 effectue une reconnexion propre. Il vaut généralement mieux laisser agir la logique de reconnexion de discord.js, mais pour les états « zombies » ce dernier recours est sûr.
Questions fréquentes
Puis-je garder mon bot en ligne 24/7 sur un hébergement gratuit (comme Replit) ?
La plupart des offres gratuites mettent le processus en veille en l'absence de trafic ; la voie la plus fiable vers un vrai uptime 24/7 est donc un petit VPS. Les astuces de ping « keep-alive » sont fragiles et violent les conditions d'utilisation de nombreuses plateformes. Pour un seul bot, un VPS à quelques euros par mois plus pm2 est bien plus fiable.
Devrais-je utiliser systemd ou Docker plutôt que pm2 ?
Les trois sont valables. systemd est intégré à Linux et offre des redémarrages au niveau service ; Docker fait de même avec une politique restart: unless-stopped. L'atout de pm2, c'est que la collecte des logs, les redémarrages basés sur la mémoire et l'ergonomie comme pm2 status tiennent dans un seul outil. Si vous utilisez déjà Docker, la politique de redémarrage du conteneur suffit généralement.
Comment stopper une boucle de redémarrage qui ne cesse de planter ?
min_uptime et max_restarts existent précisément pour cela : si le bot plante trop souvent dans une courte fenêtre, pm2 abandonne. À ce moment-là, utilisez pm2 logs pour trouver la cause racine (souvent un token invalide, une variable d'environnement manquante ou une erreur dure levée dans le code) et corrigez-la.
Votre bot tombe-t-il encore sans raison apparente ? Je peux mettre en place la détection de crash, la configuration pm2 et la surveillance par healthcheck à votre place ; pour une infrastructure de bot résiliente et auto-réparatrice, contactez-moi.