Search code examples
javascriptdiscorddiscord.js

Issue: DiscordJS App crashes when a command is run multiple times in a row


I have been playing around with the Slash Commands options that DiscordJS added in V13. I have created my command and event handlers, and everything boots up just fine.

The current behavior is:

1.) Boots up with no problem. All confirmation messages load in console and commands are registered

2.) When running the /ping command for the first time in the Discord channel I received the below message Discord Error Message

3.) When running the /ping command for the second time I get a successful response of "Pong!" in the channel I entered the command into

4.) When running the /ping command for the third time I get a successful response of "Pong!" but the bot crashes with the below error message

C:\Users\XXXX\Documents\bot\discordBot\node_modules\discord.js\src\structures\interfaces\InteractionResponses.js:94
    if (this.deferred || this.replied) throw new Error('INTERACTION_ALREADY_REPLIED');
                                             ^

Error [INTERACTION_ALREADY_REPLIED]: The reply to this interaction has already been sent or deferred.
    at CommandInteraction.reply (C:\Users\XXXX\Documents\bot\discordBot\node_modules\discord.js\src\structures\interfaces\InteractionResponses.js:94:46)
    at Client.<anonymous> (C:\Users\XXXX\Documents\bot\discordBot\events\interactionCreate.js:17:23)
    at processTicksAndRejections (node:internal/process/task_queues:96:5) {
  [Symbol(code)]: 'INTERACTION_ALREADY_REPLIED'
}

I am running out of ideas on how to resolve this. I have tried in the Ping command a number of reply options to the interaction but none have corrected the issue. Has anyone run into this?

I have a full code sample on my Github for review: https://github.com/DBAggie/discordBot/tree/dev


Solution

  • Ok after a few tests, I find where's the problem. You just listen to the event again for every interactionCreate fired.

    So first it won't respond. And listen for a new interactionCreate event.

    Before

    module.exports = {
        name: 'interactionCreate',
        execute(interaction, client) {
            client.on('interactionCreate', async interaction => {
                console.log(`hit the interaction create script`)
                if (!interaction.isCommand()) return console.log('Not a valid command');
    
                const command = client.commands.get(interaction.commandName);
    
                if (!command) return;
    
                try {
                    console.log('Trying to execute')
                    await command.execute(interaction);
                } catch (error) {
                    await interaction.reply({
                        content: 'There was an error while executing this command!',
                        ephemeral: true
                    });
                }
                console.log('Below the catch');
            });
            //console.log('Below the below catch message');
        }
    };
    

    After

    module.exports = {
        name: "interactionCreate",
        async execute(interaction, client) {
            console.log(`hit the interaction create script`);
            if (!interaction.isCommand()) return console.log("Not a valid command");
    
            const command = client.commands.get(interaction.commandName);
    
            if (!command) return;
    
            try {
                console.log("Trying to execute");
                await command.execute(interaction);
            } catch (error) {
                await interaction.reply({
                    content: "There was an error while executing this command!",
                    ephemeral: true,
                });
            }
            console.log("Below the catch");
            //console.log('Below the below catch message');
        },
    };
    

    See here? You listen for a new event when every interaction.

    execute(interaction, client) {
        client.on('interactionCreate', async interaction => {