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

Discord.js验证命令报错:TypeError: Cannot read properties of undefined (reading 'channels')

Discord机器人验证命令发送消息失败:TypeError: Cannot read properties of undefined (reading 'channels')

错误信息

TypeError: Cannot read properties of undefined (reading 'channels')

出错代码片段

const channel = client.channels.cache.get('1133739855042596955');
const response = channel.send({ 
  embeds: [ embedconfirmar ],
  components: [row]
});

问题背景

开发Discord机器人的验证命令时,使用上述代码向指定频道发送消息触发报错。已尝试将client替换为message.client或interaction.client,问题仍未解决。以下是命令文件和index.js的完整代码:

命令文件

const { SlashCommandBuilder, EmbedBuilder, ButtonBuilder, ButtonStyle, ActionRowBuilder } = require('discord.js');

module.exports = {
  data: new SlashCommandBuilder()
    .setName('verificacion')
    .setDescription('Comando para verificarte')
    .addStringOption(option =>
      option.setName('idroblox')
        .setDescription('nombre de usuario de roblox')
        .setRequired(true))
        .addStringOption(option =>
      option.setName('idrp')
        .setDescription('Nombre RP')
        .setRequired(true)),

  async execute(interaction, message, client) {
    if (interaction.member.roles.cache.has('1138094416364589137')) {
      await interaction.reply({ content: 'Ya estas verificado', ephemeral: true });
    } else {
      const discorduser = interaction.user
      const robloxuser = interaction.options.getString('idroblox')
      const roleplayuser = interaction.options.getString('idrp')

      const embedconfirmar = new EmbedBuilder()
        .setTitle("¿Verificar miembro")
        .setDescription("Si los datos son correctos pulse aceptar.")
        .addFields(
          {
            name: "Discord",
            value: `${discorduser}`,
          },
          {
            name: "ROBLOX",
            value: `${robloxuser}`,
          },
          {
            name: "Nombre RP",
            value: `${roleplayuser}`,
          },
        )
        .setColor("#00b0f4")
        .setFooter({
          text: "Sistema de verificacion - Asturias RP",
          iconURL: "https://cdn.discordapp.com/icons/1133734868598149121/ca3ff37bd87df6c771613abaeb49afc4.webp?size=96",
        })
        .setTimestamp();

      const memberr = interaction.member; // Guild member
      const interactionUser = interaction.user

      const embedvcancelada = new EmbedBuilder()
        .setTitle("Error")
        .setDescription("Un moderador ha cancelado la verificacion")
        .setColor("#f50000")
        .setFooter({
          text: "Sistema de verificacion - Asturias RP",
        })
        .setTimestamp();

      const embedvcanceladamd = new EmbedBuilder()
        .setTitle("Solicitud de verificacion rechazada")
        .setDescription("Un moderador ha cancelado la verificacion, vuelve a intentarlo rellenando bien los datos.Si se te sigue recazando la solicitud o crees que es un error contacta con un <@1133748311355035768> o <@1133748206463885333>")
        .setColor("#f50000")
        .setFooter({
          text: "Sistema de verificacion - Asturias RP",
        })
        .setTimestamp();

      const confirmar = new ButtonBuilder()
        .setCustomId('confirmar')
        .setLabel('Confirmar')
        .setStyle(ButtonStyle.Success);

      const cancelar = new ButtonBuilder()
        .setCustomId('cancelar')
        .setLabel('Cancelar')
        .setStyle(ButtonStyle.Danger);

      const row = new ActionRowBuilder()
        .addComponents(cancelar, confirmar);

      const channel = client.channels.cache.get('1133739855042596955');
      const response = channel.send({ 
        embeds: [ embedconfirmar ],
        components: [row]
      });

      const embedexito = new EmbedBuilder()
        .setTitle("Exito!")
        .setDescription("El usuario ha sido verificado")
        .setColor("#04f500")
        .setFooter({
          text: "Sistema de verificacion - Asturias RP",
        })
        .setTimestamp();

      const embedexitomd = new EmbedBuilder()
        .setTitle("Verificacion Completada")
        .setDescription("Has sido verificado en Asturias RP, recuerda leer las <#1133737727465103421>")
        .setColor("#04f500")
        .setFooter({
          text: "Sistema de verificacion - Asturias RP",
        })
        .setTimestamp();

      try {
        const confirmation = await response.awaitMessageComponent();

        if (confirmation.customId === 'confirm') {
          await confirmation.update({ content: 'Verificado', components: [] });

          const guild = interaction.guild
          const role = guild.roles.cache.find(role => role.name === 'Verificado'); // Find role named "Verificado" in cached roles
        
          await memberr.roles.add(role); // Add role to member

          memberr.setNickname(`${robloxuser}`)

          await interaction.reply({ embeds: [ embedexito ] });

          interactionUser.send({ embeds: [embedexitomd] })

          interactionUser.send({ embeds: [embedexito] })
        } else if (confirmation.customId === 'cancelar') {
          await confirmation.update({ content: 'Cancelado', components: [] });
          await interaction.reply({ embeds: [ embedvcancelada ] })

          interactionUser.send({embeds: [embedvcancelada]})
        }
      } catch (e) {
        console.log('')
      }
    }
  },
};

index.js

// Require the necessary discord.js classes
const fs = require('node:fs');
const path = require('node:path');
const { Client, Collection } = require('discord.js');
const { token } = require('./config.json');

// Create a new client instance
const client = new Client({ intents: 3276799 });

client.commands = new Collection();

const foldersPath = path.join(__dirname, 'commands');
const commandFolders = fs.readdirSync(foldersPath);

for (const folder of commandFolders) {
    const commandsPath = path.join(foldersPath, folder);
    const commandFiles = fs.readdirSync(commandsPath).filter(file => file.endsWith('.js'));
    for (const file of commandFiles) {
        const filePath = path.join(commandsPath, file);
        const command = require(filePath);
        // Set a new item in the Collection with the key as the command name and the value as the exported module
        if ('data' in command && 'execute' in command) {
            client.commands.set(command.data.name, command);
        } else {
            console.log(`[WARNING] The command at ${filePath} is missing a required "data" or "execute" property.`);
        }
    }
}

const eventsPath = path.join(__dirname, 'events');
const eventFiles = fs.readdirSync(eventsPath).filter(file => file.endsWith('.js'));

for (const file of eventFiles) {
    const filePath = path.join(eventsPath, file);
    const event = require(filePath);
    if (event.once) {
        client.once(event.name, (...args) => event.execute(...args));
    } else {
        client.on(event.name, (...args) => event.execute(...args));
    }
}


// When the client is ready, run this code (only once)
// We use 'c' for the event parameter to keep it separate from the already defined 'client'


// Log in to Discord with your client's token
client.login(token);

修复方案

1. 修正execute函数参数顺序

斜杠命令的execute函数仅接收interaction和client两个参数,你额外添加的message参数会导致client被赋值为undefined,这是报错的核心原因。修改命令文件中的execute函数定义:

async execute(interaction, client) {
  // 原有代码逻辑
}

2. 可靠获取频道

使用fetch方法替代cache.get,缓存中不存在频道时会自动从API拉取,同时增加错误处理:

// 替换原有的频道获取代码
const channel = await client.channels.fetch('1133739855042596955');
if (!channel) {
  console.error('无法找到指定的审核频道');
  return await interaction.reply({ content: '内部错误:无法找到验证审核频道', ephemeral: true });
}
// 注意加上await,确保消息发送完成
const response = await channel.send({ 
  embeds: [ embedconfirmar ],
  components: [row]
});

3. 修复按钮交互的ID拼写错误

按钮的customId是confirmar,但你的判断条件写的是'confirm',导致确认按钮无法触发正确逻辑,修正为:

if (confirmation.customId === 'confirmar') {
  // 原有确认逻辑
}

4. 额外优化建议

  • 所有异步操作(如channel.send、awaitMessageComponent)都要添加await,避免Promise未正确处理。
  • 获取角色时使用ID而非名称:guild.roles.cache.get('1138094416364589137'),避免角色名称修改后代码失效。
  • 给memberr.setNickname添加错误处理,避免因权限不足导致报错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 20:24:52