使用pycord/discord.py的discord.ui选择菜单出现Unknown interaction错误
问题描述
开发一款带选择菜单交互的Discord机器人,用于切换用户角色,但代码偶尔出现故障,终端抛出错误,具体分三种情况:
- 机器人成功添加所选角色,但Discord显示“此交互失败”且终端报错
- 机器人未执行角色操作,Discord显示“此交互失败”且终端报错
- 完全正常运行无错误
代码片段
import discord from discord.ext import commands from discord.ui import View, Select intents = discord.Intents.default() intents.members = True intents.message_content = True bot = commands.Bot(command_prefix='!', intents=intents) @bot.command() async def select(ctx): embed = discord.Embed(title="", description="Choose your color:\n🔴 - Red\n🟢 - Green\n🔵 - Blue", color=discord.Color.orange()) async def select_callback(interaction): user = interaction.user r = discord.utils.get(ctx.guild.roles, name="Vermelho") g = discord.utils.get(ctx.guild.roles, name="Verde") b = discord.utils.get(ctx.guild.roles, name="Azul") await user.remove_roles(r, g, b) role = discord.utils.get(ctx.guild.roles, name=str(select.values[0])) await user.add_roles(role) await interaction.response.defer() select = Select( min_values=1, max_values=1, placeholder="Choose your color here", options={discord.SelectOption(emoji="🔴", label="Vermelho", description="Color red"), discord.SelectOption(emoji="🟢", label="Verde", description="Color green"), discord.SelectOption(emoji="🔵", label="Azul", description="Color blue"),} ) select.callback = select_callback view = View(timeout=None) view.add_item(select) await ctx.send(embed=embed, view=view) @bot.event async def on_ready(): print("Running") bot.run('TOKEN')
报错信息
ERROR discord.ui.view Ignoring exception in view <View timeout=None children=1> for item <Select placeholder='Choose your color here' min_values=1 max_values=1 disabled=False options={<SelectOption label='Verde' value='Verde' description='Color green' emoji=<PartialEmoji animated=False name='🟢' id=No ne> default=False>, <SelectOption label='Azul' value='Azul' description='Color blue' emoji=<PartialEmoji animated=False name='🔵' id=None> default=False>, <SelectOption label='Vermelho' value='Vermelho' description='Color red' emoji=<PartialEmoji animated=False name='🔴' id=None> default=False>}> Traceback (most recent call last): File "C:\Users\Miguel\Desktop\Programação\Projetos\Python\Bots\Cosk Bot\venv\lib\site-packages\discord\ui\view.py", line 425, in _scheduled_task await item.callback(interaction) File "c:\Users\Miguel\Desktop\Programação\Projetos\Python\Bots\Cosk Bot\aaaa.py", line 28, in select_callback await interaction.response.defer() File "C:\Users\Miguel\Desktop\Programação\Projetos\Python\Bots\Cosk Bot\venv\lib\site-packages\discord\interactions.py", line 636, in defer await adapter.create_interaction_response( File "C:\Users\Miguel\Desktop\Programação\Projetos\Python\Bots\Cosk Bot\venv\lib\site-packages\discord\webhook\async_.py", line 218, in request raise NotFound(response, data) discord.errors.NotFound: 404 Not Found (error code: 10062): Unknown interaction
解决方案
问题原因
报错Unknown interaction的核心原因是:Discord要求交互必须在3秒内得到响应,原代码中先执行remove_roles和add_roles操作,这些操作可能因网络延迟或服务器负载耗时超过3秒,导致后续调用defer时,Discord已认定交互失效,返回404错误。此外代码还存在两个小问题:
- Select的
options使用集合({}),集合是无序结构,会导致菜单选项顺序随机 - 依赖
ctx.guild获取服务器角色,不如直接用交互上下文的interaction.guild可靠
修改后的代码
import discord from discord.ext import commands from discord.ui import View, Select intents = discord.Intents.default() intents.members = True intents.message_content = True bot = commands.Bot(command_prefix='!', intents=intents) @bot.command() async def select(ctx): embed = discord.Embed( title="", description="Choose your color:\n🔴 - Red\n🟢 - Green\n🔵 - Blue", color=discord.Color.orange() ) async def select_callback(interaction): # 先响应交互,避免超时(ephemeral=True让响应仅对用户可见) await interaction.response.defer(ephemeral=True) user = interaction.user guild = interaction.guild # 获取所有颜色角色 color_roles = [ discord.utils.get(guild.roles, name="Vermelho"), discord.utils.get(guild.roles, name="Verde"), discord.utils.get(guild.roles, name="Azul") ] # 过滤掉不存在的角色 existing_roles = [role for role in color_roles if role is not None] # 移除旧角色 if existing_roles: await user.remove_roles(*existing_roles) # 获取选中的角色 selected_role_name = select.values[0] target_role = discord.utils.get(guild.roles, name=selected_role_name) # 添加新角色(判断角色存在) if target_role: await user.add_roles(target_role) # 发送确认消息 await interaction.followup.send(f"已切换角色为 {selected_role_name}!", ephemeral=True) else: await interaction.followup.send("目标角色不存在,请联系管理员。", ephemeral=True) # 用列表定义options,保证顺序稳定 select = Select( min_values=1, max_values=1, placeholder="Choose your color here", options=[ discord.SelectOption(emoji="🔴", label="Vermelho", description="Color red"), discord.SelectOption(emoji="🟢", label="Verde", description="Color green"), discord.SelectOption(emoji="🔵", label="Azul", description="Color blue") ] ) select.callback = select_callback view = View(timeout=None) view.add_item(select) await ctx.send(embed=embed, view=view) @bot.event async def on_ready(): print("Running") bot.run('TOKEN')
关键修改点
- 优先响应交互:将
await interaction.response.defer()移到回调函数最开头,确保在3秒内完成Discord的交互响应要求 - 修复选项顺序:将Select的
options从集合改为列表,保证菜单选项顺序和定义一致 - 角色存在性检查:过滤不存在的角色,避免因角色未创建导致的报错
- 使用交互上下文:用
interaction.guild替代ctx.guild,贴合交互场景的上下文逻辑 - 添加反馈消息:通过
interaction.followup.send()给用户发送操作结果,提升体验
内容的提问来源于stack exchange,提问作者Miguelito 200
相关产品推荐
相关产品推荐

