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

discord.js响应交互时向MessageEmbed附加文件失败问题

问题根因

你遇到的DiscordAPIError: Unknown interaction错误码10062,核心原因是Discord交互的响应令牌有效期仅为3秒,你当前的代码逻辑在触发交互后没有在3秒内给出响应,导致令牌失效。

  • 不带附件时,文件读取、Embed生成的总耗时刚好卡在3秒阈值内,所以能正常返回
  • 携带附件时,多了附件序列化、上传预处理的开销,总耗时超过3秒,Discord侧已经销毁了该交互记录,因此返回未知交互错误

解决方案

1. 提前给交互发送延迟响应(必改)

对于需要进行异步IO(比如读本地文件、请求接口)的交互逻辑,必须在3秒内先调用deferReply占位,将交互的有效响应时间延长到15分钟。

2. 优化异步逻辑,避免回调地狱

将回调式的fs.readFile改为Promise版本,配合async/await简化异步流程,同时提前缓存静态数据避免重复读磁盘。

3. 延迟响应完成后使用editReply返回最终内容


修改后代码

sdg函数修改

const Discord = require('discord.js');
const fs = require('fs/promises'); // 改用Promise版本的fs
const path = require('path');

const p = path.join(__dirname, '..', 'static', 'SDGs.json');
// 提前缓存SDG数据,避免每次调用都读磁盘
let sdgCache = null;
(async () => {
  try {
    const data = await fs.readFile(p);
    sdgCache = JSON.parse(data);
  } catch (err) {
    console.error('SDG数据加载失败:', err.message);
  }
})();

module.exports = async (msg, int, text, sDGNo) => {
  // 如果是交互触发,先发送延迟响应
  if (int) {
    await int.deferReply();
  }
  // 等待缓存加载完成(如果还没加载完的话)
  while (!sdgCache) {
    await new Promise(resolve => setTimeout(resolve, 100));
  }

  if (Number(sDGNo) === 0) {
    const imgFilePath = path.join(__dirname, '..', 'static', 'SDGIcons', 'SDG_Wheel_Transparent_WEB.png');
    const imgAttachment = new Discord.MessageAttachment(imgFilePath, 'SDG_Wheel_Transparent_WEB.png');

    const goals = [];
    for (let i = 1; i < 18; i++) {
      const sdg = sdgCache[i];
      goals.push({ name: `${i} ${sdg.shortForm}`, value: `${sdg.shortFormJap}\n${sdg.shortFormNep}`, inline: true });
    }
    const embed = new Discord.MessageEmbed()
      .setTitle('Sustainable Development Goals')
      .setColor('#ffffff')
      .setThumbnail('attachment://SDG_Wheel_Transparent_WEB.png')
      .addFields(goals)
      .setFooter('To find out more about each goal, simply type "!sdg" and the goal number (e.g., "!sdg7").');

    if (msg) {
      await msg.channel.send({ embeds: [embed], files: [imgAttachment] });
    } else if (int) {
      // 延迟响应后用editReply替换内容
      await int.editReply({ embeds: [embed], files: [imgAttachment] });
    }
    return;
  }
}

interactionCreate事件修改

const { nE, tJ, say, whatis, spellcheck, joke, syn, ant, tN, sdg } = require('../helpers/commands');

module.exports = (client, interaction) => {
    switch (interaction.commandName) {
        /* ... */
        case 'sdg':
            // 调用async函数,捕获异常避免崩溃
            sdg(null, interaction, null, interaction.options.data[0] ? interaction.options.data[0].value : '0').catch(console.error);
            break;
    }
};

补充注意点

  • 如果你使用的是discord.js v14及以上版本,MessageAttachment、MessageEmbed已经从discord.js主包移到了discord.js/builders包下,需要对应调整导入路径
  • 本地静态资源如果是固定不变的,也可以提前上传到CDN,直接给Embed的thumbnail填CDN链接,不用每次都传本地文件,能进一步提升响应速度

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 10:36:04