You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Discord.js分页场景下按钮报错InteractionAlreadyReplied求助

解决Discord.js分页按钮触发的InteractionAlreadyReplied错误

问题概述

在Discord.js开发中,为Vanguard捐赠列表添加分页功能后,触发了InteractionAlreadyReplied错误,提示「该交互的回复已发送或延迟」。

错误栈信息

D:Kaze\Nouzen\node_modules\discord.js\src\structures\interfaces\InteractionResponses.js:334
if (this.deferred || this.replied) throw new DiscordjsError(ErrorCodes.InteractionAlreadyReplied);
^

Error [InteractionAlreadyReplied]: The reply to this interaction has already been sent or deferred.
at ButtonInteraction.update (D:\Kaze\Nouzen\node_modules\discord.js\src\structures\interfaces\InteractionResponses.js:334:46)
at module.exports (D:\Kaze\Nouzen\src\interactions\client\mention\mentionInteraction.js:730:27)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
code: 'InteractionAlreadyReplied'
}
Node.js v18.18.1

相关代码片段

let embed = new EmbedBuilder().setColor(colorsHex.blue).setFooter({ text: discord.footer }).setTimestamp();
switch (interaction.values[0]) {
    case 'vanguard': {
        const donations = await Donation.find({ status: 'success' })
            .sort({ transactionDate: -1 })
            .lean();
        if (!donations.length) {
            embed.setTitle('Vanguard Donors').setDescription('No donations received yet.');
            return interaction.editReply({ embeds: [embed], components: [] });
        }
        const chunkSize = 5;
        const pages = [];
        for (let i = 0; i < donations.length; i += chunkSize) {
            const donorsChunk = donations.slice(i, i + chunkSize);
            const pageContent = donorsChunk.map((donor, index) =>
                `**#${i + index + 1}**\n` +
                `**Username:** ${donor.username}\n` +
                `**Amount:** ${donor.amount} ${donor.currency}\n` +
                `**Total:** ${donor.totalAmount} ${donor.currency}\n` +
                `**Platform:** ${donor.platform}\n` +
                `**Date:** <t:${Math.floor(new Date(donor.transactionDate).getTime() / 1000)}:F>\n` +
                `${donor.message ? `**Message:** ${donor.message}` : ''}`
            ).join('\n\n');
            pages.push(
                new EmbedBuilder()
                    .setTitle('Vanguard Donors')
                    .setDescription(pageContent)
                    .setColor(colorsHex.blue)
                    .setFooter({ text: `Page ${pages.length + 1} of ${Math.ceil(donations.length / chunkSize)}` })
                    .setTimestamp()
            );
        }
        const SelectionMenu = new StringSelectMenuBuilder()
            .setCustomId('VanguardSetting')
            .setPlaceholder('See more information')
            .addOptions([
                { value: 'AddUserVanguard', label: 'Add User To List', description: 'Add a new user to the vanguard list', emoji: '<a:41519headpat6:1333423950994215024>' },
                { value: 'RemoveUserVanguard', label: 'Remove User From List', description: 'Remove a user from the vanguard list', emoji: '<a:Bang_Cry:1340213607442415626>' },
                { value: 'RequestVanguard', label: 'Request To Be Vanguard', description: 'Request to be a vanguard member', emoji: '<a:9861vvblueheart:1333422925956780072>' }
            ]);
        const HomeButton = new ButtonBuilder()
            .setCustomId('home').setLabel('Domain').setEmoji('<a:house:1354060003040034900>').setStyle(ButtonStyle.Secondary);
        const PreviousButton = new ButtonBuilder()
            .setCustomId('DonationPrevious').setLabel('Previous').setEmoji('<a:arrowreverse:1342004555805888523>').setStyle(ButtonStyle.Secondary);
        const selectMenuRow = new ActionRowBuilder().addComponents(SelectionMenu);
        const buttonRow = new ActionRowBuilder().addComponents(HomeButton, PreviousButton);
        return pagination(interaction, pages, null, [selectMenuRow, buttonRow]);
    }
    // 其他case代码略
}
await interaction.update({
    embeds: [embed],
    components: [],
});
return;

问题原因

错误核心是同一个交互被多次响应:

  1. case 'vanguard'分支中调用的pagination函数已经对交互执行了回复/更新操作
  2. 当switch执行完毕后,代码会继续走到末尾的await interaction.update(...),此时交互状态已标记为replied,触发重复响应错误

修复方案

1. 调整默认响应逻辑到switch的default分支

将末尾的interaction.update移到switch的default分支中,仅当没有匹配到任何case时才执行:

switch (interaction.values[0]) {
    case 'vanguard': {
        // 现有代码...
        return pagination(interaction, pages, null, [selectMenuRow, buttonRow]);
    }
    // 其他case分支...
    default: {
        await interaction.update({
            embeds: [embed],
            components: [],
        });
        return;
    }
}

2. 确保pagination函数的交互处理正确

检查分页工具函数的实现:

  • 确认函数内部使用interaction.editReply()或interaction.reply()处理初始响应,且后续按钮回调仅使用interaction.update()更新内容
  • 避免在分页逻辑中重复调用回复类方法

3. 按钮回调中增加状态检查

在分页按钮的处理逻辑中,先判断交互状态再执行操作:

// 示例按钮回调逻辑
if (interaction.replied || interaction.deferred) {
    await interaction.editReply({ /* 更新分页内容 */ });
} else {
    await interaction.reply({ /* 初始分页内容 */ });
}

内容的提问来源于stack exchange,提问作者Kazeynx

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 11:27:38