L'erreur « discord application did not respond » qui apparaît lorsque vous lancez une commande slash est l'un des problèmes les plus fréquents — mais aussi les plus faciles à corriger — dans le développement de bots Discord. Ce message ne signifie presque jamais que votre bot est « cassé » ; il signifie qu'il n'a pas répondu à temps. Discord attend la première réponse à une interaction dans un délai de 3 secondes, et une fois cette fenêtre fermée, il affiche cette erreur à l'utilisateur quoi que fasse votre bot ensuite. Dans ce guide, j'explique la vraie cause, la règle des 3 secondes et comment bien régler votre minutage avec defer.
La règle des 3 secondes : la vraie cause
Quand un utilisateur lance une commande slash, clique sur un bouton ou choisit une option de menu, Discord envoie une interaction à votre bot. Cette interaction porte un « token » à durée de vie très courte, et Discord attend la première réponse dans les 3 secondes. Si vous n'envoyez rien dans cette fenêtre, Discord invalide l'interaction et affiche l'avertissement Application did not respond. Même si votre code se termine avec succès un instant plus tard, vous ne pouvez plus répondre à cette interaction, car le token est déjà fermé.
Voici la distinction clé : la limite de 3 secondes ne concerne que la première réponse. Une fois cette première réponse envoyée — par exemple en ouvrant un état « réflexion » — vous disposez d'environ 15 minutes pour modifier la réponse. Vous pouvez donc tout à fait exécuter des tâches longues ; il suffit de signaler « une réponse arrive » dans ces 3 premières secondes.
Gagner du temps avec defer
Chaque fois qu'une opération risque de durer plus de 3 secondes, utilisez defer. Différer indique à Discord « je prépare une réponse, patiente » et affiche à l'utilisateur l'indicateur de réflexion du bot, de sorte que la fenêtre ne se ferme jamais.
Un schéma typique avec discord.js (v14) ressemble à ceci :
module.exports = {
data: new SlashCommandBuilder()
.setName('stats')
.setDescription('Récupère les statistiques du serveur'),
async execute(interaction) {
// Accuser réception avant la fin des 3 secondes
await interaction.deferReply();
// Travail potentiellement long : appel base de données / API
const data = await fetchStats(interaction.guildId);
// Modifier la première réponse une fois prête
await interaction.editReply(`Membres au total : ${data.memberCount}`);
},
};
Côté discord.py, la logique est identique ; seule l'API change :
@tree.command(name="stats", description="Statistiques du serveur")
async def stats(interaction: discord.Interaction):
await interaction.response.defer() # respecter la règle des 3 secondes
data = await fetch_stats(interaction.guild_id)
await interaction.followup.send(f"Membres au total : {data['member_count']}")
Quand utiliser reply, editReply et followUp
Confondre les méthodes de réponse déclenche aussi cette erreur ou d'autres conflits. Un jeu de règles simple couvre presque tous les cas :
- Travail rapide (< 3 s) : appelez directement
interaction.reply(), pas besoin de defer. - Travail lent : d'abord
deferReply(), puis remplissez la première réponse aveceditReply(). - Messages supplémentaires : utilisez
followUp()après la première réponse. - Visible par l'utilisateur seul : marquez-la comme éphémère lors du defer. Sur discord.js v14.9+ utilisez
flags: MessageFlags.Ephemeral; sur les versions plus anciennes{ ephemeral: true }.
Vous ne pouvez faire la première réponse à une interaction qu'une seule fois. Si vous rappelez reply() après reply() ou deferReply(), vous obtenez l'erreur « already been acknowledged » ; à partir de là, il faut utiliser editReply() ou followUp().
Quand vos commandes ne sont pas enregistrées
Parfois le problème n'est pas le minutage : c'est que les commandes n'ont jamais été enregistrées auprès de Discord. Une ancienne définition de commande reste en cache, vous écrivez du nouveau code, mais Discord appelle l'ancienne définition et n'atteint jamais la branche concernée de votre code, donc aucune réponse n'est envoyée. Vous devez enregistrer les commandes à chaque modification :
const rest = new REST().setToken(process.env.TOKEN);
await rest.put(
Routes.applicationGuildCommands(CLIENT_ID, GUILD_ID),
{ body: commands },
);
console.log('Commandes enregistrées.');
Pendant le développement, utilisez les commandes de serveur (guild) : elles se mettent à jour instantanément. Les commandes globales se diffusent sur tous les serveurs mais leur propagation peut prendre du temps.
Attrapez les erreurs silencieuses
Le cas le plus sournois est une erreur levée entre defer et editReply. Le code plante, editReply ne s'exécute jamais, et l'utilisateur reste bloqué sur l'indicateur de réflexion ou voit une erreur. Enveloppez tout le corps de la commande dans un try/catch et transformez l'erreur en réponse visible :
async execute(interaction) {
await interaction.deferReply();
try {
const data = await operationRisquee();
await interaction.editReply(data.message);
} catch (err) {
console.error(err);
await interaction.editReply('Une erreur est survenue, peux-tu réessayer ?');
}
}
Consultez toujours vos journaux : la vraie cause s'y cache souvent (délai de base de données dépassé, intent manquant, valeur nulle).
Liste de contrôle rapide
- Le bot est-il réellement en ligne et le token est-il correct ?
- Avez-vous appelé
deferReply()/defer()avant l'opération longue ? - Utilisez-vous
editReply/followUpaprès la première réponse ? - Les commandes sont-elles enregistrées auprès de Discord (surtout les commandes de serveur) ?
- Le code est-il protégé par un
try/catchet lisez-vous les journaux ? - Les gateway intents requis sont-ils activés ?
Questions fréquentes
J'ai utilisé defer mais j'obtiens encore « application did not respond », pourquoi ?
Le plus probable est que votre appel deferReply() s'exécute après les 3 secondes ; par exemple, une requête de base de données lente précède le defer. Placez le defer tout en haut de la commande, avant tout travail lourd. Il se peut aussi que l'appel defer lui-même ne soit pas await ou qu'il lève une erreur.
Combien de temps ai-je pour modifier la réponse après les 3 secondes ?
Après le defer, le token d'interaction reste valide environ 15 minutes. Pendant ce délai, vous pouvez envoyer des réponses avec editReply et followUp. Pour des tâches de plus de 15 minutes, préférez un message de salon classique.
Les interactions de bouton et de menu suivent-elles la même règle ?
Oui. Boutons, menus déroulants et envois de modal sont tous des interactions et suivent la même règle des 3 secondes. Si le travail prend du temps, vous devez aussi les différer.
Votre bot bloque toujours ? Je peux mettre en place le flux d'interaction, l'enregistrement des commandes et le minutage de bout en bout pour que votre bot reste fiable. Contactez-moi et réglons cela ensemble.