Discord.js中play指令触发InteractionAlreadyReplied错误求助
Discord.js + WOKCommands 音乐Bot play指令触发InteractionAlreadyReplied错误排查
问题描述
开发Discord Bot音乐功能时,执行play指令频繁触发InteractionAlreadyReplied错误。指令内所有回复逻辑均通过return终止代码,但仍无法解决报错,无法定位问题。
错误信息
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' }
使用代码
index.js
const DiscordJS = require('discord.js') const WOKCommands = require('wokcommands') const dotenv = require('dotenv') const { Player } = require('discord-player') const path = require('path') // 修复:原代码遗漏path模块引入 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)
play.js
module.exports = { category: 'Music', description: 'Play a music', slash: true, testOnly: true, guildOnly: true, skipBuiltInReply: true, // 添加配置阻止WOKCommands自动回复 options:[{ name: 'song', description: 'Song of your choice', required: true, type: 3, }], callback: async({ client, interaction, args }) => { // 定义机器人和用户的语音频道ID const myVoice = interaction.guild.members.me.voice.channelId; const memberVoice = interaction.member.voice.channelId; // 检查用户是否在语音频道 if (!memberVoice) return await interaction.reply({ content: `*You're not in the voice channel!*`, ephemeral: true }); // 检查用户是否和机器人在同一语音频道 if (myVoice && memberVoice !== myVoice) return await interaction.reply({ content: `*You're not in the same voice channel as me!*`, ephemeral: true }); // 创建播放队列 const queue = client.player.createQueue(interaction.guild, { metadata: { channel: interaction.channel } }); // 尝试连接语音频道,失败则返回错误 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 }); } // 延迟回复,显示"机器人正在思考" await interaction.deferReply(); // 搜索歌曲 const song = await client.player.search(args[0], { requestedBy: interaction.user }).then(s => s.tracks[0]); // 未找到歌曲则返回提示 if (!song) return await interaction.followUp(`*❌ | Track **${args[0]}** not found!*`); // 播放歌曲并返回提示 queue.play(song); return await interaction.followUp(`*⏳ | Queuing up song **${song.title}**!*`); } }
环境
- WokCommands命令处理器
- NodeJS 18.9
- DiscordJS v14
排查与解决方案
核心问题定位:错误栈显示WOKCommands的
invokeCommand方法在尝试调用interaction.reply,但此时我们已经手动处理了所有回复场景(包括reply或deferReply),导致重复回复报错。这是因为WOKCommands默认会在slash命令执行完毕后自动发送一个默认回复。解决步骤:
- 在
play.js的命令配置中添加skipBuiltInReply: true,阻止WOKCommands自动发送默认回复。 - 修复
index.js中遗漏的path模块引入(原代码使用path.join但未引入模块,会导致初始化报错)。
- 在
额外验证:确保所有
interaction.reply、interaction.deferReply和interaction.followUp都使用await,避免异步竞态导致的重复回复触发。
内容的提问来源于stack exchange,提问作者xscriptxdata
相关产品推荐
相关产品推荐

