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
相关产品推荐
相关产品推荐

