
Discord.py 中的 discord.ui.View 默认 180 秒后自动超时失效,导致按钮点击后提示 “Interaction failed”,本文详解如何通过设置 timeout=None 和启用持久化视图(Persistent Views)彻底解决该问题。
discord.py 中的 `discord.ui.view` 默认 180 秒后自动超时失效,导致按钮点击后提示 “interaction failed”,本文详解如何通过设置 `timeout=none` 和启用持久化视图(persistent views)彻底解决该问题。
你遇到的 Interaction failed 错误,根本原因在于 discord.ui.View 的默认生命周期限制:所有 View 实例在创建后 180 秒(3 分钟)内若无交互响应,将自动超时并禁用所有组件(包括按钮、下拉菜单等)。这正是 /add_button 发送的按钮在最初 5 分钟内可用、随后突然失效的直接原因——并非代码逻辑错误,而是 Discord.py 的内置安全机制。
✅ 解决方案一:禁用自动超时(适用于短期稳定场景)
只需在自定义 View 类中显式传入 timeout=None:
class SuggestionButtonView(discord.ui.View):
def __init__(self):
# 关键:禁用超时,使按钮长期有效(直到 bot 重启)
super().__init__(timeout=None)
@discord.ui.button(label="Enviar Sugestão", style=discord.ButtonStyle.primary, custom_id="send_suggestion")
async def button_click(self, interaction: discord.Interaction, button: discord.ui.Button):
modal = SuggestionModal()
await interaction.response.send_modal(modal)⚠️ 注意:timeout=None 仅防止运行时超时,但无法跨 bot 重启存活。一旦机器人重启,所有已发送的 View 将丢失状态,按钮点击会返回 404 Not Found 或 Interaction failed —— 因为 Discord 服务器仍持有旧 View 的 custom_id,而新进程未注册对应处理器。
✅ 解决方案二:启用持久化视图(推荐用于生产环境)
要让按钮在 bot 重启后继续工作,必须使用 Persistent Views:
- 所有 @discord.ui.button 必须带有 固定且唯一的 custom_id(你已正确使用 "send_suggestion");
- View 类需继承 discord.ui.View 并设置 timeout=None;
- 在 bot 启动时,全局复用同一个 View 实例并调用 bot.add_view()(而非每次发送新 View)。
修改后的完整实现如下:
# 在 bot 启动前或 on_ready 中初始化并注册持久化 View
persistent_view = SuggestionButtonView()
@bot.event
async def on_ready():
print(f'{bot.user} está online!')
# ⚠️ 关键:仅在此处注册一次!确保 View 生命周期与 bot 一致
bot.add_view(persistent_view)
# 更新 View 类(保持 custom_id 稳定 + timeout=None)
class SuggestionButtonView(discord.ui.View):
def __init__(self):
super().__init__(timeout=None) # 永不失效
@discord.ui.button(label="Enviar Sugestão", style=discord.ButtonStyle.primary, custom_id="send_suggestion")
async def button_click(self, interaction: discord.Interaction, button: discord.ui.Button):
modal = SuggestionModal()
await interaction.response.send_modal(modal)并在 /add_button 命令中复用该实例:
@bot.tree.command(name='add_button', description='Adicione um botão para enviar sugestões。')
@app_commands.checks.check(check_roles)
async def add_button(interaction: discord.Interaction):
try:
embed = discord.Embed(
title="Envie sua Sugestão",
description="Clique no botão abaixo para enviar sua sugestão!\n\n Com seu feedback conseguimos melhorar em vários aspectos!",
color=discord.Color.gold()
)
embed.set_author(name="Sistema de Sugestões")
embed.set_image(url="https://cdn.discordapp.com/attachments/...") # 省略
embed.set_footer(text="BOT Powered by Rodopoulos")
# 使用已注册的持久化 View 实例(非新建!)
await interaction.response.send_message(embed=embed, view=persistent_view)
except Exception as e:
print(f"Erro ao adicionar botão de sugestões: {e}")
await interaction.response.send_message("Erro ao adicionar botão de sugestões。 Por favor, tente novamente mais tarde。", ephemeral=True)? 验证与注意事项
- ✅ custom_id 必须全局唯一且硬编码不变(不可动态生成),否则重启后无法匹配;
- ✅ bot.add_view(view) 必须在 on_ready() 或更早执行,且只执行一次;
- ❌ 不要在命令中 await interaction.followup.send(..., view=SuggestionButtonView()) —— 这会创建新 View,不具持久性;
- ? 持久化 View 不保存数据,仅恢复交互能力;如需关联消息 ID 或用户状态,请结合 discord.PartialMessage 或数据库存储。
通过以上配置,你的建议按钮将真正实现「长期可用 + 重启无忧」,彻底告别 Interaction failed。

















