Discord.js V14按钮点击后Embed编辑失败且机器人崩溃问题
解决Discord.js V14 /suggest指令按钮崩溃与持久化问题
一、修复按钮点击崩溃(TypeError: Cannot read properties of undefined (reading 'find'))
这个报错的核心是调用find方法的对象为undefined,本质是获取Embed或字段时未做存在性校验,按以下步骤修正:
确保获取到目标Embed
在按钮交互处理代码中,先校验消息内的Embed是否存在:// 按钮交互逻辑内 if (!interaction.message.embeds[0]) { return interaction.reply({ content: "找不到对应的建议Embed", ephemeral: true }); } // 用EmbedBuilder克隆原Embed,避免直接修改不可变对象 const newEmbed = new EmbedBuilder(interaction.message.embeds[0]);安全获取并更新字段数值
假设Embed字段格式为✅ 同意: 0、❌ 反对: 0,添加数值解析的校验:// 处理同意按钮 const agreeField = newEmbed.data.fields.find(field => field.name === "✅ 同意"); if (!agreeField) { return interaction.reply({ content: "同意字段不存在", ephemeral: true }); } const agreeCount = parseInt(agreeField.value.split(": ")[1]); if (isNaN(agreeCount)) { return interaction.reply({ content: "无法解析同意数", ephemeral: true }); } agreeField.value = `✅ 同意: ${agreeCount + 1}`; // 同理处理反对按钮 const disagreeField = newEmbed.data.fields.find(field => field.name === "❌ 反对"); if (!disagreeField) { return interaction.reply({ content: "反对字段不存在", ephemeral: true }); } const disagreeCount = parseInt(disagreeField.value.split(": ")[1]); if (isNaN(disagreeCount)) { return interaction.reply({ content: "无法解析反对数", ephemeral: true }); } disagreeField.value = `❌ 反对: ${disagreeCount + 1}`;更新消息并响应交互
修改完成后更新消息,用deferUpdate避免交互超时:await interaction.message.edit({ embeds: [newEmbed] }); await interaction.deferUpdate();
二、实现按钮重启后仍可用(解决与interactionCreate冲突)
冲突原因是同时在指令内使用临时collector和全局interactionCreate事件处理按钮,需统一用全局事件处理:
给按钮设置带标识的自定义ID
在/suggest指令创建按钮时,将消息ID作为自定义ID的一部分,用于识别对应建议:// /suggest指令内创建按钮与消息 const suggestEmbed = new EmbedBuilder() .setTitle("新建议") .setDescription(interaction.options.getString('content')) .addFields( { name: "✅ 同意", value: "0", inline: true }, { name: "❌ 反对", value: "0", inline: true } ); const actionRow = new ActionRowBuilder().addComponents( new ButtonBuilder() .setCustomId(`suggest_agree_temp`) .setLabel("Agree") .setStyle(ButtonStyle.Success), new ButtonBuilder() .setCustomId(`suggest_disagree_temp`) .setLabel("Disagree") .setStyle(ButtonStyle.Danger) ); const suggestMessage = await interaction.channel.send({ embeds: [suggestEmbed], components: [actionRow] }); // 发送后更新按钮ID,绑定消息ID const updatedRow = new ActionRowBuilder().addComponents( new ButtonBuilder() .setCustomId(`suggest_agree_${suggestMessage.id}`) .setLabel("Agree") .setStyle(ButtonStyle.Success), new ButtonBuilder() .setCustomId(`suggest_disagree_${suggestMessage.id}`) .setLabel("Disagree") .setStyle(ButtonStyle.Danger) ); await suggestMessage.edit({ components: [updatedRow] });在interactionCreate.js内统一处理按钮
移除指令内的collector代码,全局监听按钮交互:// interactionCreate.js module.exports = { name: 'interactionCreate', async execute(interaction) { if (!interaction.isButton()) return; // 处理同意按钮 if (interaction.customId.startsWith('suggest_agree_')) { if (!interaction.message.embeds[0]) { return interaction.reply({ content: "无效的建议消息", ephemeral: true }); } const newEmbed = new EmbedBuilder(interaction.message.embeds[0]); const agreeField = newEmbed.data.fields.find(f => f.name === "✅ 同意"); if (!agreeField || isNaN(parseInt(agreeField.value.split(": ")[1]))) { return interaction.reply({ content: "字段解析失败", ephemeral: true }); } const count = parseInt(agreeField.value.split(": ")[1]) + 1; agreeField.value = `✅ 同意: ${count}`; await interaction.message.edit({ embeds: [newEmbed] }); await interaction.deferUpdate(); } // 处理反对按钮 else if (interaction.customId.startsWith('suggest_disagree_')) { if (!interaction.message.embeds[0]) { return interaction.reply({ content: "无效的建议消息", ephemeral: true }); } const newEmbed = new EmbedBuilder(interaction.message.embeds[0]); const disagreeField = newEmbed.data.fields.find(f => f.name === "❌ 反对"); if (!disagreeField || isNaN(parseInt(disagreeField.value.split(": ")[1]))) { return interaction.reply({ content: "字段解析失败", ephemeral: true }); } const count = parseInt(disagreeField.value.split(": ")[1]) + 1; disagreeField.value = `❌ 反对: ${count}`; await interaction.message.edit({ embeds: [newEmbed] }); await interaction.deferUpdate(); } } };移除指令内的临时Collector
删掉/suggest指令中类似message.createMessageComponentCollector()的代码,避免与全局事件冲突。
内容的提问来源于stack exchange,提问作者Illanser
相关产品推荐
相关产品推荐

