Discord.js collecting multiple interactions on multiple sets of buttons

67 Views Asked by At

I have a Discord.js bot that allows users to vote on the outcome of games. The admin uses a slash command that sends a message with 2 buttons attached representing the 2 possible votes. There will often be more than 1 game to vote on at a time. I am handling the interactions like this:

interaction.client.on("interactionCreate", async (i) => {
    if (!i.isButton()) return;

    let team; 

    try {
        if (i.customId === 'team1Button' || i.customId === 'team2Button') {
            // Handle team vote with retry mechanism
            await retryOperation(async () => {
                team = await getTeamEmoji(i.message.id, i.customId); // Assign value to team variable
                await castVote(team.name, i.user.username, i.message.id);
            }, 3, i.message.id, i.user.username); // Retry team vote operation up to 3 times

            // Reply to interaction
            await i.reply({
                content: `Vote for ${team.emoji} submitted.`,
                ephemeral: true,
            });
        }
    } catch (error) {
        console.error("Interaction handling error:", error);
        logError(error, i.message.id, i.user.username, 'Interaction handling error: ' + i);
    }
});

So this works. The bot never crashes and votes do go through. However, my error log ends up full of records with this message:

error
"DiscordAPIError[10062]: Unknown interaction"

or

error
"DiscordAPIError[40060]: Interaction has already been acknowledged."

But no more information than that. I further know that some interactions are failing the first time and then working after additional attempts via my retryOperation function, which if you need to see it is:

async function retryOperation(operation, maxRetries, id, username, initialDelay = 1000, maxDelay = 60000) {
    let retries = 0;
    let delay = initialDelay;
    
    while (retries < maxRetries) {
        try {
            await operation();
            return; // Operation succeeded, no need to retry
        } catch (error) {
            console.error(`Error during operation, retrying in ${delay}ms:`, error);
            logError(error, id, username, 'Error while voting for team. Retrying...');
            await new Promise(resolve => setTimeout(resolve, delay));
            delay = Math.min(delay * 2, maxDelay);
            retries++;
        }
    }
    
    throw new Error(`Operation failed after ${retries} retries.`);
}

So, why are the interactions failing sometimes? I will say that this happens far more often when multiple people are voting on multiple games at once, but that is going to be the case most of the time. What could be causing that issue? I'm not exactly sure how to debug this. I'm running the bot locally in Visual Studio. Any help greatly appreciated. If you need any additional information please let me know.

1

There are 1 best solutions below

0
Quezaquo On

I think the problem comes from waiting longer than 3 seconds. Discord interactions must respond within 3 seconds, otherwise the interaction ends and an error is returned.

Your retryOperation() has 1s or more delay so higher than 3 seconds in most of the case probably.

You can avoid this by defer the reply:

await i.deferReply({ ephemeral: true });

It would look like this. Please note, edit your reply into an editReply to avoid error

interaction.client.on("interactionCreate", async (i) => {
    if (!i.isButton()) return;

    let team; 

    try {
        if (i.customId === 'team1Button' || i.customId === 'team2Button') {
            await i.deferReply({ ephemeral: true });
            // Handle team vote with retry mechanism
            await retryOperation(async () => {
                team = await getTeamEmoji(i.message.id, i.customId); // Assign value to team variable
                await castVote(team.name, i.user.username, i.message.id);
            }, 3, i.message.id, i.user.username); // Retry team vote operation up to 3 times

            // Reply to interaction
            await i.editReply({
                content: `Vote for ${team.emoji} submitted.`,
                ephemeral: true,
            });
        }
    } catch (error) {
        console.error("Interaction handling error:", error);
        logError(error, i.message.id, i.user.username, 'Interaction handling error: ' + i);
    }
});

For your second error, Interaction has already been acknowledged this may come from a duplicate instance of your bot. So check that if your bot run in only one terminal (local or remote)