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

Discord.js机器人执行命令后触发DiscordAPIError[40060]求助

问题分析

报错DiscordAPIError[40060]: Interaction has already been acknowledged的核心原因是同一个交互被多个监听器重复处理:

  • 代码里存在两个InteractionCreate事件监听器,第一个监听器处理ping命令时调用interaction.reply()确认了交互;
  • 第二个监听器会再次捕获同一个ping交互,尝试执行命令或报错回复,此时交互已被确认,触发Discord API的重复确认限制。
解决方案

合并两个InteractionCreate监听器,确保每个交互只被处理一次,同时调整逻辑避免重复确认:

修改后的完整代码

const fs = require('node:fs');
const path = require('node:path')
const { Client, Events, GatewayIntentBits, Collection, ActionRowBuilder, EmbedBuilder, StringSelectMenuBuilder } = require('discord.js');
const { token } = require('./config.json');

const client = new Client({ intents: [GatewayIntentBits.Guilds] });
client.commands = new Collection();

const commandsPath = path.join(__dirname,'commands');
const commandFiles = fs.readdirSync(commandsPath).filter(file => file.endsWith('.js'));

for (const file of commandFiles) {
    const filePath = path.join(commandsPath,file);
    const command = require(filePath);

    if('data' in command && 'execute' in command){
        client.commands.set(command.data.name,command);
    }else{
        console.log(`[WARNING] The command at ${filePath} is missing`);
    }
}

client.once(Events.ClientReady, () => {
    console.log('Ready!');
})

// 合并后的单一InteractionCreate监听器
client.on(Events.InteractionCreate, async interaction => {
    // 处理聊天输入命令
    if (interaction.isChatInputCommand()) {
        // 单独处理ping命令(若不想移到commands文件夹)
        if (interaction.commandName === 'ping') {
            const row = new ActionRowBuilder()
                .addComponents(
                    new StringSelectMenuBuilder()
                        .setCustomId('select')
                        .setPlaceholder('Nothing selected')
                );
            const embed = new EmbedBuilder()
                .setColor(0x0099FF)
                .setTitle('pong')
                .setDescription('Some description here')
                .setImage('https://media.istockphoto.com/id/1310339617/vector/ping-pong-balls-isolated-vector-illustration.jpg?s=612x612&w=0&k=20&c=sHlz5sbJrymDo7vfTQIuaj4lbmwlvAhVE7Uk_631ZA8=')

            await interaction.reply({ content: 'Pong!', ephemeral: true, embeds: [embed]});
            // 终止后续逻辑,避免重复处理
            return;
        }

        // 处理commands文件夹中的其他命令
        const command = interaction.client.commands.get(interaction.commandName);
        if (!command) {
            console.error(`No command matching ${interaction.commandName} was found`)
            return;
        }
        try {
            await command.execute(interaction);
        } catch(error) {
            console.error(error);
            // 检查交互状态,避免重复回复
            if (interaction.replied || interaction.deferred) {
                await interaction.followUp({content: '执行命令时发生错误!', ephemeral: true});
            } else {
                await interaction.reply({content: '执行命令时发生错误!', ephemeral: true});
            }
        }
    }

    // 可在此扩展处理其他交互类型,比如按钮、选择菜单等
    // if (interaction.isStringSelectMenu()) {
    //     // 选择菜单处理逻辑
    // }
});

client.login(token);

关键改动说明

  1. 合并监听器:将两个独立的InteractionCreate监听器合并为一个,避免同一个交互被多次捕获。
  2. 终止逻辑:处理完ping命令后添加return,确保后续的命令处理代码不会重复执行。
  3. 错误处理优化:报错回复前检查interaction.replied或interaction.deferred状态,若交互已确认则改用followUp()回复,避免触发重复确认报错。

可选模块化优化

如果遵循Discord.js的命令模块化规范,可将ping命令逻辑移到commands/ping.js文件中,让代码更整洁:

commands/ping.js示例

const { SlashCommandBuilder, ActionRowBuilder, EmbedBuilder, StringSelectMenuBuilder } = require('discord.js');

module.exports = {
    data: new SlashCommandBuilder()
        .setName('ping')
        .setDescription('回复Pong!'),
    async execute(interaction) {
        const row = new ActionRowBuilder()
            .addComponents(
                new StringSelectMenuBuilder()
                    .setCustomId('select')
                    .setPlaceholder('未选择任何内容')
            );
        const embed = new EmbedBuilder()
            .setColor(0x0099FF)
            .setTitle('pong')
            .setDescription('一些描述内容')
            .setImage('https://media.istockphoto.com/id/1310339617/vector/ping-pong-balls-isolated-vector-illustration.jpg?s=612x612&w=0&k=20&c=sHlz5sbJrymDo7vfTQIuaj4lbmwlvAhVE7Uk_631ZA8=');

        await interaction.reply({ content: 'Pong!', ephemeral: true, embeds: [embed]});
    },
};

此时主文件的InteractionCreate监听器可简化为:

client.on(Events.InteractionCreate, async interaction => {
    if (!interaction.isChatInputCommand()) return;

    const command = interaction.client.commands.get(interaction.commandName);
    if (!command) {
        console.error(`未找到匹配${interaction.commandName}的命令`)
        return;
    }
    try {
        await command.execute(interaction);
    } catch(error) {
        console.error(error);
        if (interaction.replied || interaction.deferred) {
            await interaction.followUp({content: '执行命令时发生错误!', ephemeral: true});
        } else {
            await interaction.reply({content: '执行命令时发生错误!', ephemeral: true});
        }
    }
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 01:11:31