Discord.js 14.15.3交互已确认错误(40060)修复求助
修复DiscordAPIError[40060]: Interaction has already been acknowledged
问题原因
你的错误核心有两个:
- 交互超时未响应:创建工单转录(
transcripts.createTranscript)可能耗时超过3秒,Discord要求所有交互必须在3秒内确认,超时后会自动标记为已确认,后续再调用submitted.update就会触发40060错误。 - 交互对象误用:你试图用模态框提交的交互(
submitted)去更新原始按钮的消息,这是错误的用法,应该直接操作触发模态框的按钮消息(interaction.message)。
修复后的代码
const { ActionRowBuilder, EmbedBuilder, ButtonBuilder, WebhookClient, ModalBuilder, TextInputBuilder, TextInputStyle, } = require('discord.js'); const transcripts = require('discord-html-transcripts'); module.exports = { data: { name: 'cerrarticket', }, async execute(interaction, client, args) { const webhook = new WebhookClient({ url: client.config.webhook.tickets, }); if (!interaction.member.roles.cache.has(client.config.lf.staffRoleId)) { return interaction.reply({ content: 'Only staff can use this!', ephemeral: true, }); } const modal = new ModalBuilder() .setCustomId('closeticket') .setTitle('Ticket close form') .addComponents( new ActionRowBuilder().addComponents( new TextInputBuilder() .setCustomId('reason') .setLabel('Why do you want to close the ticket?') .setStyle(TextInputStyle.Paragraph), ), ); await interaction.showModal(modal); const submitted = await interaction .awaitModalSubmit({ time: 60000, filter: (i) => i.user.id === interaction.user.id, }) .catch((err) => { return null; }); if (submitted) { // 立即延迟响应,避免交互超时 await submitted.deferReply({ ephemeral: true }); const reason = submitted.fields.getTextInputValue('reason'); const channel = submitted.channel; const ownerTicket = submitted.guild.members.cache.get(args[0]); // 执行耗时的转录创建操作 const attachment = await transcripts.createTranscript(channel, { saveImages: true, }); // 禁用原始按钮(操作触发模态框的按钮消息) await interaction.message.edit({ components: [ new ActionRowBuilder().addComponents( interaction.message.components[0].components.map(btn => ButtonBuilder.from(btn).setDisabled(true) ), ), ], }); // 发送处理成功的提示 await submitted.followUp({ content: 'The ticket has entered the closing process correctly!', ephemeral: true, }); // 发送关闭倒计时消息 await channel.send({ embeds: [ new EmbedBuilder() .setColor('#701196') .setDescription('The ticket will be closed in 5 seconds...'), ], }); // 延迟删除频道 setTimeout(async () => { if (channel) await channel.delete().catch(() => null); }, 5000); // 发送转录到webhook await webhook.send({ content: '<:Vacio:1286828514770812948>', embeds: [ new EmbedBuilder() .setColor('#701196') .setDescription(`# 📝 Transcript`) .setTimestamp() .addFields( { name: 'Ticket', value: `#${channel.name} (${channel.id})`, }, { name: 'Panel', value: `${channel.name.split('-')[0].charAt(0).toUpperCase() + channel.name.split('-')[0].slice(1)}`, }, { name: 'Owner', value: `**[@${ownerTicket.user.username}]** (${ownerTicket.user.id})\n<:Vacio:1286828514770812948>`, }, { name: 'Moderator', value: `**[@${submitted.user.username}]** (${submitted.user.id})`, }, { name: 'Reason', value: `${reason}`, }, ), ], files: [attachment], }).catch(() => null); } }, };
关键修复点说明
- 立即延迟响应:在拿到
submitted后第一时间调用submitted.deferReply({ephemeral: true}),告诉Discord"我稍后再响应",避免3秒超时自动确认。 - 修改原始按钮状态:用
interaction.message.edit()替代submitted.update(),直接修改触发模态框的按钮消息,禁用按钮。 - 异步操作顺序调整:把耗时的转录创建放在延迟响应之后,确保交互不会超时。
内容的提问来源于stack exchange,提问作者user27414786
相关产品推荐
相关产品推荐

