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

discord.py中on_raw_reaction_add报NoneType属性错误如何解决

报错原因

两处报错的核心原因是member变量实际值为None,对空值调用实例方法必然触发属性不存在错误,具体诱因如下:

  • Guild.get_member()方法仅从discord.py客户端的本地缓存查询成员数据,不会主动请求Discord开放接口,以下场景都会导致查询返回空值:
    • 机器人刚启动,尚未完成目标服务器的成员列表缓存加载
    • 目标服务器成员数达到大服务器阈值,客户端默认不缓存离线成员
    • 反应触发用户近期没有产生过会被客户端记录的交互事件,不在本地缓存内
  • 代码未做触发主体过滤:如果是机器人自身给目标消息添加了对应表情,也会触发这段逻辑,极易引发异常
  • 代码存在冗余查询和空值判断缺失:重复调用bot.get_guild()获取服务器对象,且未判断服务器、目标角色是否查询成功,极端场景下会触发同类空值报错
修复方法
  1. 第一步直接过滤机器人自身触发的反应事件,避免无意义的逻辑执行
  2. 把表情、频道、消息ID的匹配判断放到逻辑最前面,不匹配直接终止,减少无效的接口/缓存查询
  3. 复用服务器对象,避免重复查询;增加角色、成员的空值校验
  4. 成员查询优先走本地缓存,缓存未命中时调用异步方法guild.fetch_member()主动从Discord接口拉取用户数据,不依赖本地缓存

注意:如果调用fetch_member时提示无权限,需要前往Discord开发者后台,在机器人的「Privileged Gateway Intents」配置中开启Server Members Intent开关;同时要保证机器人在服务器内拥有「管理角色」权限,且机器人自身的角色排序高于要分配的「Bro」角色,否则加角色操作会失败。

修复后可运行代码
from discord.utils import get

@bot.event
async def on_raw_reaction_add(payload):
    # 过滤机器人自身的反应事件
    if payload.user_id == bot.user.id:
        return
    
    # 提前校验反应、频道、消息是否匹配目标规则,不匹配直接退出
    if (payload.emoji.name != "bro_emoji" 
        or payload.channel_id != 920004461575954472 
        or payload.message_id != 920004958923939901):
        return

    guild = bot.get_guild(payload.guild_id)
    if not guild:
        return
    
    bro_role = get(guild.roles, name="Bro")
    if not bro_role:
        print("未找到名称为Bro的角色,分配角色终止")
        return

    # 优先读缓存,缓存不存在主动拉取成员数据
    member = guild.get_member(payload.user_id)
    if not member:
        try:
            member = await guild.fetch_member(payload.user_id)
        except Exception as e:
            print(f"获取触发反应的成员失败: {str(e)}")
            return

    print('Role acquired')
    await member.add_roles(bro_role)
    await member.send("Bro role acquired")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.22 16:12:26