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

DiscordJS v13石头剪刀布命令触发Interaction Failed无报错排查

问题排查与修复方案

核心错误点(直接导致Interaction Failed)

  • 未定义button变量:代码中直接调用button.deferUpdate()、判断button.id,但collect事件返回的交互实例是参数i,不存在全局button对象,直接抛出未捕获异常,交互未在3秒内响应就会触发失败提示
  • 未等待deferUpdate执行:deferUpdate是异步方法,不加await会导致交互还没完成延期响应就开始处理后续逻辑,依旧可能超时
  • 收集器绑定位置错误:在collect事件内部绑定collector.on("end"),每触发一次按钮点击就会重复绑定一次end事件,逻辑混乱
  • 重复生成机器人出拳值:已经在逻辑开头生成botPick赋值botChoose,后续每个按钮判断分支又重新生成botPick但未更新botChoose,导致出拳逻辑完全混乱
  • 变量名冲突:发送按钮消息后的回调参数命名为message,和外层触发指令的message变量重名,容易出现取值错误
  • 收集器创建对象错误:使用channel.createMessageComponentCollector会监听整个频道的所有组件交互,应该绑定到你刚发送的带按钮的消息上

修复后完整代码

const { MessageActionRow, MessageButton, MessageEmbed } = require('discord.js');
module.exports = new Command({
    name: 'rps',
    description: "play rock paper scissors",
    permission: "ADMINISTRATOR",

    async run(message, args, client) {
        let botChoose;
        let playerScore = 0;
        let botScore = 0;
        const rock = ":fist: Rock";
        const paper = ":hand_splayed: Paper";
        const scissor = ":v: Scissor";

        const rockButton = new MessageButton().setCustomId("rock").setStyle('SECONDARY').setLabel("Rock");
        const paperButton = new MessageButton().setCustomId("paper").setStyle('SECONDARY').setLabel("Paper");
        const scissorButton = new MessageButton().setCustomId("scissor").setStyle('SECONDARY').setLabel("Scissor");
        const row = new MessageActionRow().addComponents([rockButton, paperButton, scissorButton]);

        const embed = new MessageEmbed()
        .setColor("RANDOM")
        .setDescription("Winner: **-**")
        .addField(`Score RPS`, `\`->\` ${message.author}: **${playerScore} Point**\n\`->\` ${client.user}: **${botScore} Point**`)

        // 重命名回调参数避免重名
        message.channel.send({ embeds: [embed], components: [row] }).then(async (sentMsg) => {
            const ifilter = i => i.user.id === message.author.id;
            // 绑定到发送的消息本身创建收集器
            const collector = sentMsg.createMessageComponentCollector({ filter: ifilter, time: 30000 })

            collector.on("collect", async i => {
                // 正确调用延期响应,加await
                await i.deferUpdate();

                // 生成机器人出拳,删掉后续重复生成的冗余代码
                const botPick = Math.floor(Math.random() * 3) + 1;
                if (botPick === 1) botChoose = "rock";
                else if (botPick === 2) botChoose = "paper";
                else if (botPick === 3) botChoose = "scissor";

                const embed1 = new MessageEmbed()
                .setColor("RANDOM")
                .setDescription('Winner: **-**')
                .addField(`Score RPS`, `\`->\` ${message.author}: **${playerScore} Point**\n\`->\` ${client.user}: **${botScore} Point**`)

                // 正确从交互实例取customId判断按钮
                if (i.customId === "rock") {
                    if (botChoose === "paper") {
                        botScore++;
                        const embed2 = new MessageEmbed()
                        .setColor("RANDOM")
                        .setDescription('Winner: **-**')
                        .addField(`Score RPS`, `\`->\` ${message.author}: **${playerScore} Point**\n\`->\` ${client.user}: **${botScore} Point**`)
                        return sentMsg.edit({ content: `I picked: **${paper}**\nYou picked: **${rock}**\n**Result**: You lost`, embeds: [embed2], components: [row] })
                    }
                    if (botChoose === "rock") {
                        return sentMsg.edit({ content: `I picked: **${rock}**\nYou picked: **${rock}**\n**Result**: We tied`, embeds: [embed1], components: [row] })
                    }
                    if (botChoose === "scissor") {
                        playerScore++;
                        const embed2 = new MessageEmbed()
                        .setColor("RANDOM")
                        .setDescription('Winner: **-**')
                        .addField(`Score RPS`, `\`->\` ${message.author}: **${playerScore} Point**\n\`->\` ${client.user}: **${botScore} Point**`)
                        return sentMsg.edit({ content: `I picked: **${scissor}**\nYou picked: **${rock}**\n**Result**: You Won`, embeds: [embed2], components: [row] })
                    }
                }

                if (i.customId === "paper") {
                    if (botChoose === "scissor") {
                        botScore++;
                        const embed2 = new MessageEmbed()
                        .setColor("RANDOM")
                        .setDescription('Winner: **-**')
                        .addField(`Score RPS`, `\`->\` ${message.author}: **${playerScore} Point**\n\`->\` ${client.user}: **${botScore} Point**`)
                        return sentMsg.edit({ content: `I picked: **${scissor}**\nYou picked: **${paper}**\n**Result**: You lost`, embeds: [embed2], components: [row] })
                    }
                    if (botChoose === "paper") {
                        return sentMsg.edit({ content: `I picked: **${paper}**\nYou picked: **${paper}**\n**Result**: We tied`, embeds: [embed1], components: [row] })
                    }
                    if (botChoose === "rock") {
                        playerScore++;
                        const embed2 = new MessageEmbed()
                        .setColor("RANDOM")
                        .setDescription('Winner: **-**')
                        .addField(`Score RPS`, `\`->\` ${message.author}: **${playerScore} Point**\n\`->\` ${client.user}: **${botScore} Point**`)
                        return sentMsg.edit({ content: `I picked: **${rock}**\nYou picked: **${paper}**\n**Result**: You Won`, embeds: [embed2], components: [row] })
                    }
                }

                if (i.customId === "scissor") {
                    if (botChoose === "rock") {
                        botScore++;
                        const embed2 = new MessageEmbed()
                        .setColor("RANDOM")
                        .setDescription('Winner: **-**')
                        .addField(`Score RPS`, `\`->\` ${message.author}: **${playerScore} Point**\n\`->\` ${client.user}: **${botScore} Point**`)
                        return sentMsg.edit({ content: `I picked: **${rock}**\nYou picked: **${scissor}**\n**Result**: You lost`, embeds: [embed2], components: [row] })
                    }
                    if (botChoose === "scissor") {
                        return sentMsg.edit({ content: `I picked: **${scissor}**\nYou picked: **${scissor}**\n**Result**: We tied`, embeds: [embed1], components: [row] })
                    }
                    if (botChoose === "paper") {
                        playerScore++;
                        const embed2 = new MessageEmbed()
                        .setColor("RANDOM")
                        .setDescription('Winner: **-**')
                        .addField(`Score RPS`, `\`->\` ${message.author}: **${playerScore} Point**\n\`->\` ${client.user}: **${botScore} Point**`)
                        return sentMsg.edit({ content: `I picked: **${paper}**\nYou picked: **${scissor}**\n**Result**: You Won`, embeds: [embed2], components: [row] })
                    }
                }
            })

            // end事件移到collect事件外面绑定
            collector.on("end", async(x) => {
                if (x.size === 0) {
                    sentMsg.edit({ content: `No one even played againts me lol!`, embeds: [], components: [] });
                } else {
                    if (playerScore === botScore) {
                        const embed2 = new MessageEmbed()
                        .setColor("BLACK")
                        .setDescription('Winner: **TIED**')
                        .addField(`Score RPS`, `\`->\` ${message.author}: **${playerScore} Point**\n\`->\` ${client.user}: **${botScore} Point**`)
                        sentMsg.edit({ content: "", embeds: [embed2], components: [] })
                    } else if (playerScore > botScore) {
                        const embed2 = new MessageEmbed()
                        .setColor("GREEN")
                        .setDescription(`Winner: **${message.author}**`)
                        .addField(`Score RPS`, `\`->\` ${message.author}: **${playerScore} Point**\n\`->\` ${client.user}: **${botScore} Point**`)
                        sentMsg.edit({ content: "", embeds: [embed2], components: [] })
                    } else {
                        const embed2 = new MessageEmbed()
                        .setColor("RED")
                        .setDescription(`Winner: **${client.user}**`)
                        .addField(`Score RPS`, `\`->\` ${message.author}: **${playerScore} Point**\n\`->\` ${client.user}: **${botScore} Point**`)
                        sentMsg.edit({ content: "", embeds: [embed2], components: [] })
                    }
                }
            })
        })
    }
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 07:09:04