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

使用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')

关键修改点

  1. 优先响应交互:将await interaction.response.defer()移到回调函数最开头,确保在3秒内完成Discord的交互响应要求
  2. 修复选项顺序:将Select的options从集合改为列表,保证菜单选项顺序和定义一致
  3. 角色存在性检查:过滤不存在的角色,避免因角色未创建导致的报错
  4. 使用交互上下文:用interaction.guild替代ctx.guild,贴合交互场景的上下文逻辑
  5. 添加反馈消息:通过interaction.followup.send()给用户发送操作结果,提升体验

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 10:25:35