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

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

排查与解决方案

  1. 核心问题定位:错误栈显示WOKCommands的invokeCommand方法在尝试调用interaction.reply,但此时我们已经手动处理了所有回复场景(包括reply或deferReply),导致重复回复报错。这是因为WOKCommands默认会在slash命令执行完毕后自动发送一个默认回复。

  2. 解决步骤:

    • 在play.js的命令配置中添加skipBuiltInReply: true,阻止WOKCommands自动发送默认回复。
    • 修复index.js中遗漏的path模块引入(原代码使用path.join但未引入模块,会导致初始化报错)。
  3. 额外验证:确保所有interaction.reply、interaction.deferReply和interaction.followUp都使用await,避免异步竞态导致的重复回复触发。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 23:35:21