DiscordJS v14 guildCreate事件报错:Cannot read properties of undefined (reading 'has')
DiscordJS v14 guildCreate事件报错:Cannot read properties of undefined (reading 'has')
问题场景
基于DiscordJS v14开发guildCreate事件,需求是机器人被添加到服务器时,自动向有权限发送消息的文本频道发送欢迎消息,但触发事件后出现报错:
Cannot read properties of undefined (reading 'has')
初始代码:
const embed = new EmbedBuilder() .setDescription('Hi') .setColor('Blue') let channel = guild.channels.cache.find( channel => channel.type === ChannelType.GuildText && channel.permissionsFor(guild.me.has(PermissionsBitField.Flag.SendMessages)) ); channel.send({ embeds: [embed] })
修改后的代码(问题仍存在):
const embed = new EmbedBuilder() .setDescription('Hi') .setColor('Blue') let channel = guild.channels.cache.find( channel => channel.type === ChannelType.GuildText && channel.permissionsFor(guild.me).has(PermissionsBitField.Flag.SendMessages) ); channel.send({ embeds: [embed] })
问题原因
报错核心是guild.me为undefined——机器人刚加入服务器时,Discord的缓存还未同步完成,此时直接访问guild.me无法获取到机器人的成员对象,导致后续调用.has()时触发“读取undefined属性”的错误。另外,即使频道查找逻辑正常,也未处理“找不到可发送消息的频道”的情况,会引发新的报错。
修复方案
关键修改点
- 手动获取机器人的成员对象:用
await guild.members.fetch(client.user.id)替代依赖缓存的guild.me,确保能拿到有效对象。 - 增加错误捕获:对成员获取、消息发送等异步操作添加错误处理,避免程序崩溃。
- 增加空值判断:检查找到的频道是否存在,防止调用
send()时出错。
修正后的完整代码
const { EmbedBuilder, ChannelType, PermissionsBitField } = require('discord.js'); module.exports = { name: 'guildCreate', async execute(guild, client) { const embed = new EmbedBuilder() .setDescription('Hi') .setColor('Blue'); // 手动获取机器人在当前服务器的成员信息,绕过缓存未同步问题 const botMember = await guild.members.fetch(client.user.id).catch(err => { console.error('获取机器人成员信息失败:', err); return null; }); if (!botMember) return; // 筛选出机器人有权限发送消息的文本频道 const targetChannel = guild.channels.cache.find(channel => channel.type === ChannelType.GuildText && channel.permissionsFor(botMember).has(PermissionsBitField.Flags.SendMessages) ); if (targetChannel) { targetChannel.send({ embeds: [embed] }).catch(err => { console.error('发送欢迎消息失败:', err); }); } else { console.log('当前服务器中未找到机器人有权限发送消息的文本频道'); } } };
补充说明
guildCreate事件处理函数需要标记为async,因为使用了await关键字。- 调用
fetch()时添加catch块,能在获取成员失败时输出错误信息,方便排查权限或网络问题。 - 最终判断
targetChannel是否存在,避免因找不到频道导致的后续报错。
内容的提问来源于stack exchange,提问作者SadSenpai
相关产品推荐
相关产品推荐

