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

Discord Slash Commands执行报Unknown interaction错误排查

问题根因

你遇到的报错和错误数量匹配的核心原因是INTERACTION_CREATE事件监听器被重复注册:
你把client.ws.on('INTERACTION_CREATE', ...)的监听逻辑放在了ready事件的回调函数内部,每当你的bot触发一次ready事件(包括启动、断连重连),都会新增一个独立的交互事件监听器,不会自动移除旧的监听器。
当有交互触发时,所有注册的监听器都会同时执行:第一个监听器调用send()方法成功响应交互后,Discord 端的交互凭证会立即失效,剩下的监听器再尝试调用同一个交互的send()方法时,就会抛出Unknown interaction错误,错误次数等于监听器注册总数减1,和你描述的现象完全吻合。

其他潜在问题

  1. 你每次启动都会全量POST注册全局斜杠命令,全局命令有1小时的CDN缓存,频繁注册会触发Discord API限流,开发阶段建议优先使用服务器级别的斜杠命令,缓存仅1秒,调试更高效。
  2. 交互响应逻辑没有加异常捕获,未处理的Promise rejection会导致Node进程异常退出。
  3. 你使用的是discord.js的底层WS事件和HTTP API,v13版本已经内置了interactionCreate高层事件封装,无需手动处理WS事件。

修复方案

1. 调整事件监听位置

将交互监听器从ready回调中移出,全局只注册一次:

const { fs, Discord, erros, colors, emojis, database } = require('../../exports.js');
const slash = [];

// 预加载命令列表
const arquivos = fs.readdirSync("./src/slash").filter((file) => file.endsWith(".js"))
for (const files of arquivos) {
  const file = require(`../../slash/${files}`);
  slash.push(file);
}

module.exports = async (client) => {
  // 注册命令:仅示例,生产环境建议做增量更新
  for (const file of slash) {
    await client.api.applications(client.user.id).commands.post({data: file.data})
  }
}

// 全局只注册一次交互监听器
client.ws.on('INTERACTION_CREATE', async (i) => {
  try {
    const command = slash.find(cmd => cmd.data.name === i.data.name.toLowerCase())
    if(command) await command.execute(client, send, i);
  } catch (err) {
    console.error('交互处理错误:', err)
  }
})

async function send(interaction, content) {
  return client.api.interactions(interaction.id, interaction.token).callback.post({
    data: {
      type: 4,
      data: await msg(interaction, content),
    },
  });
}

async function msg(i, c) {
  const m = await Discord.APIMessage.create(client.channels.resolve(i.channel_id), c)
    .resolveData()
    .resolveFiles();
  return { ...m.data, files: m.files }
}

module.exports.help = {
  name: "ready",
  title: "Comandos slashs"
}

2. 可选:升级为discord.js v13原生交互处理

v13版本已经内置了完整的斜杠命令处理能力,无需手动调用底层API,你可以直接用官方封装的方法:

// 监听交互事件
client.on('interactionCreate', async interaction => {
  if (!interaction.isChatInputCommand()) return;
  const command = slash.find(cmd => cmd.data.name === interaction.commandName);
  if (!command) return;
  try {
    await command.execute(interaction);
  } catch (err) {
    console.error(err);
    await interaction.reply({ content: '命令执行出错', ephemeral: true });
  }
});

对应的say命令可以简化为:

const { Discord, erros, colors, emojis, database, titles} = require('../exports.js');

module.exports = {
  data: {
    name: "say",
    description: "Faça o bot falar",
    options: [{
      name: "text", 
      description: "texto que vai na mensagem",
      type: 3,
      required: true
    }]
  },
  async execute (interaction) {
    const texto = interaction.options.getString('text');
    await interaction.reply(texto);
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.21 22:45:04