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

discord.js检测角色变更时出现Cannot read property 'id' of undefined报错如何解决

问题根源

你现有代码存在2个核心错误:

  1. 逻辑错误:你把oldMember(GuildMember对象)直接和test2(布尔值)做大小比较,这段判断逻辑完全不生效
  2. 缓存读取失败:从你打印的GuildMember结构可以看到guild.roles.cache是空集合,你没有开启对应网关意图,也没有优先读取稳定的角色字段导致调用报错

前置配置检查

确认你实例化bot时已经开启了GuildMembers和Guilds网关意图,这是discord.js v13+版本读取成员角色信息的必要配置,代码示例:

const { Client, Intents } = require('discord.js');
const bot = new Client({
  intents: [
    Intents.FLAGS.GUILDS,
    Intents.FLAGS.GUILD_MEMBERS,
    // 其他你需要的业务相关意图
  ]
});

未开启对应意图时角色缓存会为空,就会出现你遇到的Cannot read property "id" of undefined报错。

修复后的事件代码

/// 检测成员付费角色增减
bot.on('guildMemberUpdate', async (oldMember, newMember) => {
  // 建议环境变量中直接存付费角色ID,比角色名判断更稳定(角色名可修改ID全局唯一)
  const PAID_ROLE_ID = process.env.PAID_ROLE;
  
  // 分别判断新旧成员状态是否持有付费角色
  const hadPaidRole = oldMember.roles.cache.has(PAID_ROLE_ID);
  const hasPaidRole = newMember.roles.cache.has(PAID_ROLE_ID);

  // 付费角色状态未变化直接返回,不执行无效逻辑
  if (hadPaidRole === hasPaidRole) return;

  // 付费角色新增逻辑
  if (hasPaidRole) {
    console.log(`用户${newMember.user.id}获得付费角色,开始更新数据库`);
    // 此处补充你新增付费用户的数据库更新逻辑
  } 
  // 付费角色移除逻辑
  else {
    console.log(`用户${newMember.user.id}失去付费角色,开始更新数据库`);
    // 此处补充你移除付费用户的数据库更新逻辑
  }
});

补充优化建议

  • 如果你坚持使用角色名判断,或者环境变量中存的是角色名,可将判断逻辑改为r => r.name === process.env.PAID_ROLE,你原有代码里的${[process.env.PAID_ROLE]}写法冗余且易出问题
  • 如果还是出现缓存为空的问题,可以改用GuildMember自带的原生_roles字段判断,这是直接存储角色ID的数组,不需要走缓存读取,更稳定:
    const hadPaidRole = oldMember._roles.includes(PAID_ROLE_ID);
    const hasPaidRole = newMember._roles.includes(PAID_ROLE_ID);
    
  • 你之前尝试对比roles.cache.size的逻辑容易误判,比如用户同时增减两个非付费角色时也会触发无效的数据库更新,直接判断付费角色的持有状态变化更精准

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.11 04:45:00