Discord.js - Error: InteractionAlreadyReplied

Viewed 30

I have recently started adding some music functionalities to my bot I am creating. However, I constantly run into an issue when trying to execute command play. The command play has few interaction.reply and interaction.followUp replies to return, however few only execute when IF statement is met, and some only follow up to interaction.deferReply.

From what I can see, all replies are mostly running when IF statement is executed, but all of them are returning the reply, meaning they should stop the code once they finish returning them. But the bot however still tells me that Interaction was already replied, yet I can't see where.

Error:

C:\Users\xscriptxdata\Desktop\Bot\node_modules\discord.js\src\structures\interfaces\InteractionResponses.js:101
   if (this.deferred || this.replied) throw new Error(ErrorCodes.InteractionAlreadyReplied);
                                            ^

Error [InteractionAlreadyReplied]: The reply to this interaction has already been sent or deferred.
   at ChatInputCommandInteraction.reply (C:\Users\xscriptxdata\Desktop\Bot\node_modules\discord.js\src\structures\interfaces\InteractionResponses.js:101:46)
   at SlashCommands.invokeCommand (C:\Users\xscriptxdata\Desktop\Bot\node_modules\wokcommands\dist\SlashCommands.js:185:33)
   at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
 code: 'InteractionAlreadyReplied'
}

And here is my code that bot runs with~

index.js:

const DiscordJS = require('discord.js')
const WOKCommands = require('wokcommands')
const dotenv = require('dotenv')
const { Player } = require('discord-player')
dotenv.config()
const testServer = process.env.TEST_SERVERS.split(",") 

const client = new DiscordJS.Client({
    intents: [
        "Guilds",
        "GuildMessages",
        "GuildMessageReactions",
        "GuildVoiceStates",
        "GuildMembers"
    ],
})

const player = new Player(client, {
    autoSelfDeaf: true,
    leaveOnEmpty: true,
    leaveOnEmptyCooldown: 5,
    leaveOnEnd: false,
    leaveOnStop: false,
});
client.player = player;

client.on('ready', () => {
    console.log(`${client.user?.tag} is ready to work!`)

    const wok = new WOKCommands(client, {
        commandsDir: path.join(__dirname, 'cmds'),
        testServers: testServer,
        botOwners: process.env.BOT_OWNER,
        debug: true,
        ignoreBots: true,
        disabledDefaultCommands: [
            'help',
            'command',
            'language',
            'prefix',
            'requiredrole',
            'channelonly'
        ],
    })
})

client.login(process.env.BOT_TOKEN)

And the play commmand~

play.js:

module.exports = {
    category: 'Music',
    description: 'Play a music',

    slash: true,
    testOnly: true,
    guildOnly: true,

    options:[{
        name: 'song',
        description: 'Song of your choice',
        required: true,
        type: 3,
    }],

    callback: async({ client, interaction, args }) => {

        // SPECIFY VOICE CHANNELS OF BOT AND MEMBER
        const myVoice = interaction.guild.members.me.voice.channelId;
        const memberVoice = interaction.member.voice.channelId;

        // CHECK IF MEMBER IS IN VOICE CHANNEL
        if (!memberVoice) return await interaction.reply({
            content: `*You're not in the voice channel!*`,
            ephemeral: true
        });

        // IF BOT IS IN THE VOICE CHANNEL, CHECK IF MEMBER IS IN SAME ONE/NONE
        if (myVoice && memberVoice !== myVoice) return await interaction.reply({
            content: `*You're not in the same voice channel as me!*`,
            ephemeral: true
        });

        // CREATE QUEUE
        const queue = client.player.createQueue(interaction.guild, {
            metadata: {
                channel: interaction.channel
            }
        });

        // TRIES TO CONNECT TO VOICE CHANNEL, THROWS AN ERROR ON FAIL
        try {
            if (!queue.connection) await queue.connect(interaction.member.voice.channel);
        } catch (e) {
            console.log(`Issue connecting bot to voice channel, error:\n${e}`)
            queue.destroy()
            return await interaction.reply({
                content: `*Couldn't join the voice channel!*`,
                ephemeral: true
            });
        }

        // Bot is thinking...
        await interaction.deferReply();

        // SEARCHES FOR THE SONG
        const song = await client.player.search(args[0], {
            requestedBy: interaction.user
        }).then(s => s.tracks[0]);

        // IF SONG IS NOT FOUND
        if (!song) return await interaction.followUp(`*❌ | Track **${args[0]}** not found!*`);

        // SONG IS FOUND AND PLAYS
        queue.play(song);
        return await interaction.followUp(`*⏳ | Queuing up song **${song.title}**!*`);

    }
}

I used Command Handler WokCommands and I am running NodeJS version 18.9 & DiscordJS v14.

Any help is more than appreciated.

2 Answers

I'm not sure, but I think it is because of the await in front of all your interaction.reply() and interaction.followUp(). So it will reply that, and if there is an error with your try-catch, it will try to reply again, causing it to fail because it has already been replied. Again, I'm not 100% sure, but try to not use await in front of your interaction reply or follow up, rather just return interaction.reply() or followUp().

Since you are using defer-replying method, followUp() method will make your bot do interaction twice. So instead of followUp() method, you need to do editReply() method so your bot will edit the defer-replying message and not throwing the error.

Related