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

使用discord.js开发私有Bot时client.commands为空的问题求助

Discord.js机器人执行命令时client.commands为空的排查与解决

问题描述

近期使用discord.js开发私有Discord机器人,初期运行状态正常:机器人登录无异常、Slash命令注册后输入“/”可正常显示、机器人出现在服务器成员列表中。但执行从其他项目复制的确认可用的命令时,触发如下报错:

TypeError: Cannot read properties of undefined (reading 'get')
    at Object.execute (..\moderationbot\src\events\general\interactionCreate.js:14:41)
    at Client.<anonymous> (..\moderationbot\src\deployEvents.js:22:58)
    at Client.emit (node:events:513:28)
    at InteractionCreateAction.handle (..\moderationbot\node_modules\discord.js\src\client\actions\InteractionCreate.js:97:12)
    at module.exports [as INTERACTION_CREATE] (..\moderationbot\node_modules\discord.js\src\client\websocket\handlers\INTERACTION_CREATE.js:4:36)
    at WebSocketManager.handlePacket (..\moderationbot\node_modules\discord.js\src\client\websocket\WebSocketManager.js:352:31)
    at WebSocketShard.onPacket (..\moderationbot\node_modules\discord.js\src\client\websocket\WebSocketShard.js:494:22)
    at WebSocketShard.onMessage (..\moderationbot\node_modules\discord.js\src\client\websocket\WebSocketShard.js:328:10)
    at callListener (..\moderationbot\node_modules\ws\lib\event-target.js:290:14)
    at WebSocket.onMessage (..\moderationbot\node_modules\ws\lib\event-target.js:209:9)
Emitted 'error' event on Client instance at:
    at emitUnhandledRejectionOrErr (node:events:394:10)
    at process.processTicksAndRejections (node:internal/process/task_queues:84:21)

报错指向interactionCreate.js中尝试读取client.commands.get()时,client.commands未定义。已在index.js中定义client实例,在deployCommands.js中设置client.commands并导入到interactionCreate.js,但问题仍存在。

排查与解决步骤

1. 确认client.commands的初始化位置

如果deployCommands.js是单独运行的Slash命令注册脚本,该脚本内的client实例与机器人主进程的client实例完全独立,这里设置的client.commands不会同步到主进程。必须在机器人主进程(index.js)中初始化client.commands:

// index.js 主进程代码示例
const { Client, Collection, GatewayIntentBits } = require('discord.js');
const client = new Client({ intents: [GatewayIntentBits.Guilds] });

// 初始化commands集合
client.commands = new Collection();

// 加载所有命令文件
const fs = require('fs');
const commandFiles = fs.readdirSync('./src/commands').filter(file => file.endsWith('.js'));

for (const file of commandFiles) {
  const command = require(`./src/commands/${file}`);
  // 将命令添加到集合中,key为命令名称
  client.commands.set(command.data.name, command);
}

client.login('你的机器人Token');

2. 确保事件处理中使用的是同一个client实例

如果在interactionCreate.js中导入的是新创建的client实例,而非主进程中已初始化commands的实例,会导致client.commands为空。有两种解决方式:

  • 方式一:直接导入主进程的client实例
    // interactionCreate.js
    const client = require('../../index.js');
    
    module.exports = {
      name: 'interactionCreate',
      execute(interaction) {
        if (!interaction.isChatInputCommand()) return;
    
        const command = client.commands.get(interaction.commandName);
        if (!command) return;
    
        // 执行命令逻辑
        try {
          await command.execute(interaction);
        } catch (error) {
          console.error(error);
          await interaction.reply({ content: '执行命令时出错!', ephemeral: true });
        }
      },
    };
    
  • 方式二:部署事件时传递client实例
    // deployEvents.js 加载事件时传递client
    const fs = require('fs');
    const path = require('path');
    
    module.exports = (client) => {
      const eventFolders = fs.readdirSync(path.join(__dirname, 'events'));
    
      for (const folder of eventFolders) {
        const eventFiles = fs.readdirSync(path.join(__dirname, 'events', folder)).filter(file => file.endsWith('.js'));
        for (const file of eventFiles) {
          const event = require(path.join(__dirname, 'events', folder, file));
          if (event.once) {
            client.once(event.name, (...args) => event.execute(...args, client));
          } else {
            client.on(event.name, (...args) => event.execute(...args, client));
          }
        }
      }
    };
    
    对应的interactionCreate.js接收client参数:
    module.exports = {
      name: 'interactionCreate',
      execute(interaction, client) {
        if (!interaction.isChatInputCommand()) return;
    
        const command = client.commands.get(interaction.commandName);
        // ...后续逻辑
      },
    };
    

3. 检查命令文件的加载逻辑

确认命令文件路径正确,且每个命令文件正确导出data和execute属性,data.name必须与注册到Discord的命令名称一致。例如一个标准命令文件:

// src/commands/ping.js
const { SlashCommandBuilder } = require('discord.js');

module.exports = {
  data: new SlashCommandBuilder()
    .setName('ping')
    .setDescription('回复Pong!'),
  async execute(interaction) {
    await interaction.reply('Pong!');
  },
};

4. 分离命令部署与机器人运行逻辑

单独的deployCommands.js仅负责将命令注册到Discord API,不需要在其中处理client.commands。示例部署脚本:

// deployCommands.js
const { REST, Routes } = require('discord.js');
const { clientId, guildId, token } = require('./config.json');
const fs = require('fs');

const commands = [];
const commandFiles = fs.readdirSync('./src/commands').filter(file => file.endsWith('.js'));

for (const file of commandFiles) {
  const command = require(`./src/commands/${file}`);
  commands.push(command.data.toJSON());
}

const rest = new REST({ version: '10' }).setToken(token);

(async () => {
  try {
    console.log(`正在刷新 ${commands.length} 条Slash命令...`);

    const data = await rest.put(
      Routes.applicationGuildCommands(clientId, guildId),
      { body: commands },
    );

    console.log(`成功重新加载 ${data.length} 条Slash命令`);
  } catch (error) {
    console.error(error);
  }
})();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 10:50:03