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

如何解决Discord.js按钮触发INTERACTION_ALREADY_REPLIED错误

问题原因

  • 重复注册事件监听器:你将interactionCreate按钮监听逻辑写在了/menu命令的execute函数内部,每调用一次/menu命令就会新增一个监听器实例。多次调用后点击一次按钮会触发多个监听器同时回复同一个交互,直接触发INTERACTION_ALREADY_REPLIED重复回复报错。
  • client参数未正确传递:报错提示读取on属性失败,说明你在入口文件index.js中调用命令的execute方法时,没有将client实例作为第二个参数传入,导致client变量为undefined。
  • await使用场景错误:await关键字仅可在被async标记的函数内部使用,你将带await的代码挪出async函数范围就会触发对应的语法报错。
  • 掷点逻辑不规范:原有掷d20的代码Math.round(Math.random() * 20)取值范围为020,不符合标准d20骰子120的取值规则。

修复方案

1. 调整menu.js代码

移除命令内部的事件监听逻辑,仅保留菜单生成功能:

//Remember to run " node deploy-commands.js " to register your commands!

const { SlashCommandBuilder } = require('@discordjs/builders');
const { MessageActionRow, MessageButton } = require('discord.js');

module.exports = {
    data: new SlashCommandBuilder()
        .setName('menu')
        .setDescription('打开主菜单'),
    async execute(interaction) {
        const row = new MessageActionRow()
            .addComponents(
                new MessageButton()
                    .setCustomId('dice-button')
                    .setLabel('骰子袋')
                    .setStyle("DANGER"),
                new MessageButton()
                    .setCustomId('spells-button')
                    .setLabel('法术')
                    .setStyle("PRIMARY"),
                new MessageButton()
                    .setCustomId('inventory-button')
                    .setLabel('背包')
                    .setStyle("SUCCESS"),
            );
        await interaction.reply({content: '主菜单', ephemeral: true, components: [row]})
    },
};

2. 调整入口文件index.js代码

在全局仅注册一次事件监听器,同时确保命令执行时参数传递正确:

// 原有index.js的初始化逻辑保持不变,仅修改交互处理部分
client.on('interactionCreate', async interaction => {
    // 处理斜杠命令
    if (interaction.isCommand()) {
        const command = client.commands.get(interaction.commandName);
        if (!command) return;
        try {
            // 此处传入client(如果后续不需要用也可以不传)
            await command.execute(interaction, client);
        } catch (error) {
            console.error(error);
            if (!interaction.replied && !interaction.deferred) {
                await interaction.reply({ content: '命令执行出错', ephemeral: true });
            }
        }
        return;
    }

    // 处理按钮交互
    if (interaction.isButton()) {
        // 仅响应菜单相关按钮,避免干扰其他功能的按钮
        const menuButtonIds = ['dice-button', 'spells-button', 'inventory-button'];
        if (!menuButtonIds.includes(interaction.customId)) return;
        // 避免重复回复
        if (interaction.replied || interaction.deferred) return;
        // 标准1~20掷点逻辑
        const d20Result = Math.floor(Math.random() * 20) + 1;
        await interaction.reply(`${interaction.user} 掷出了 ${d20Result}`);
    }
});

3. 其他注意事项

所有带await的代码必须放在标记了async的函数内部,不要随意将这类代码移出async函数范围,即可避免对应的语法报错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 14:15:03