遭遇DiscordAPIError 40060错误,请求技术协助排查修复
解决DiscordAPIError 40060: "Interaction has already been acknowledged"错误
这个错误的核心原因是同一个Discord交互被多次调用确认方法(如reply()/deferReply())。你的代码存在两个关键问题:
- 命令执行的错误处理逻辑中,未检查交互是否已被回复,直接再次调用
interaction.reply(),导致重复确认。 - 拆分的两个
InteractionCreate监听器虽然通过类型判断过滤,但代码结构不够严谨,存在潜在的重复处理风险。
修复后的代码
index.js
const fs = require('node:fs'); const path = require('node:path'); const { Events, Collection, ActivityType } = require('discord.js'); const client = require('./client.js'); 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 a required "data" or "execute" property.`); } } // 合并所有交互处理逻辑到单个监听器 client.on(Events.InteractionCreate, async interaction => { // 处理模态框提交 if (interaction.isModalSubmit()) { if (interaction.customId === 'myModal') { try { await interaction.reply({ content: 'Your submission was received successfully!' }); const good = interaction.fields.getTextInputValue('good'); const bot = interaction.fields.getTextInputValue('bot'); // 先获取用户再发送,避免缓存不存在的情况 const targetUser = await client.users.fetch('821682594830614578'); await targetUser.send(`good: "${good}"\nbot: "${bot}" from ${interaction.user.username}`); } catch (error) { console.error(error); // 检查交互状态,避免重复确认 if (interaction.replied || interaction.deferred) { await interaction.followUp({ content: '提交处理时发生错误!', ephemeral: true }); } else { await interaction.reply({ content: '提交处理时发生错误!', ephemeral: true }); } } } return; } // 处理斜杠命令 if (!interaction.isChatInputCommand()) return; const command = interaction.client.commands.get(interaction.commandName); if (!command) { console.error(`No command matching ${interaction.commandName} was found.`); if (!interaction.replied && !interaction.deferred) { await interaction.reply({ content: '未找到匹配的命令!', ephemeral: true }); } 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 }); } } }); client.once(Events.ClientReady, c => { client.user.setActivity('you or i have no food', { type: ActivityType.Watching }); console.log(`Logged in as ${c.user.tag}`); }); client.login(process.env.token);
ping.js(优化往返延迟计算)
const { SlashCommandBuilder } = require('discord.js'); const client = require('./../client.js'); module.exports = { data: new SlashCommandBuilder() .setName('ping') .setDescription('Ping! Pong!'), async execute(interaction) { // 获取回复消息时间戳,计算准确往返延迟 const sent = await interaction.reply({ content: `Websocket heartbeat: ${client.ws.ping} ms.`, fetchReply: true }); await interaction.editReply(`Websocket heartbeat: ${client.ws.ping} ms. Roundtrip latency: ${sent.createdTimestamp - interaction.createdTimestamp} ms.`); }, };
关键修改说明
- 合并交互监听器:将模态框和斜杠命令的处理逻辑整合到同一个监听器,避免多个监听器同时处理交互的潜在冲突。
- 检查交互状态:在所有可能回复的逻辑中,先判断
interaction.replied或interaction.deferred,已确认的交互使用followUp()替代reply(),彻底避免重复确认。 - 优化用户消息发送:使用
client.users.fetch()确保目标用户存在(即使不在缓存中),同时添加异常捕获,避免发送消息失败影响交互回复。 - 完善ping命令功能:修复原代码中往返延迟为NaN的问题,通过
fetchReply获取回复时间戳计算真实延迟。
内容的提问来源于stack exchange,提问作者realguystuff
相关产品推荐
相关产品推荐

