discord.py中斜杠命令触发Unknown interaction(404)错误的求助
discord.py中斜杠命令触发Unknown interaction(404)错误的求助
兄弟,这个bug卡一周确实够闹心的!我之前也踩过类似的坑,帮你捋捋核心问题——你遇到的Unknown interaction(404),根源是对Discord交互的响应时机太晚,再加上同步代码阻塞了事件循环,双重坑叠一起了。
问题出在哪?
Discord对斜杠命令有个硬要求:必须在3秒内对交互做出响应(要么直接发消息,要么用defer告诉Discord“我正在处理,稍后给结果”)。如果超过3秒没任何动作,Discord会直接把这个交互标记为“已失效”,之后再调用defer或者followup自然就会报404。
看你现在的代码逻辑:
# 先同步调用外部API(耗时操作) response = retrieval.conversation_manager.get_response(text_to_send) # 才告诉Discord我要处理 await interaction.response.defer()
这完全搞反了!同步的requests请求会直接卡住整个bot的事件循环,等API返回结果时,早就超过3秒的窗口了,Discord已经不认这个交互了,哪怕你后面发普通字符串也没用。
怎么修复?
按这几步来,保证解决问题:
先defer,抢占3秒窗口
只要通过了频道权限检查,第一件事就是调用defer,把交互的超时时间延长到15分钟,给后续操作争取时间。把同步请求改成异步
同步的requests会阻塞asyncio事件循环,导致bot整个卡住,必须换成异步HTTP库aiohttp,让事件循环能正常处理其他任务。调整代码顺序
权限检查 → 立即defer → 处理耗时逻辑 → 用followup发结果
修改后的代码示例
main.py 关键部分修改
@tree.command(name="name", description="description") async def faaq( interaction: discord.Interaction, text_to_send: str, ): # 先做频道检查,这个很快,不会超时 if interaction.channel_id != settings.CHANNEL_ID: await interaction.response.send_message( "This command can't be used in this channel.", ephemeral=True ) return # 关键!立即defer,必须在3秒内执行 await interaction.response.defer(ephemeral=True) # 现在再去调用异步的API请求 response = await retrieval.conversation_manager.get_response(text_to_send) # 用followup发送最终结果 await interaction.followup.send(f"{response}", ephemeral=True)
retrieval.py 改成异步版本
import aiohttp import settings import asyncio headers = { "x-api-key": settings.CHATPDF_API_KEY, "Content-Type": "application/json", } async def qa_bot(question): data = { "sourceId": settings.SOURCE_ID, "messages": [ { "role": "user", "content": question, } ], } # 用aiohttp做异步请求,不阻塞事件循环 async with aiohttp.ClientSession() as session: async with session.post( "https://api.chatpdf.com/v1/chats/message", headers=headers, json=data ) as response: if response.status == 200: result = await response.json() return result["content"] else: print("Status:", response.status) print("Error:", await response.text()) return "抱歉,获取回答时出现错误,请稍后再试。" class ConversationManager: async def get_response(self, query): response = await qa_bot(query) return response conversation_manager = ConversationManager() # 本地测试的CLI也改成异步 async def test_cli(): while True: user_input = input("User: ") if user_input.lower() == "exit": print("Bot: Goodbye!") break response = await conversation_manager.get_response(user_input) print("Bot:", response) if __name__ == "__main__": asyncio.run(test_cli())
额外提醒
- 测试的时候,一定要确保
defer是第一个和交互相关的操作(除了快速的权限检查),哪怕你后面sleep30秒再发消息,也不会再报404了。 defer的时候可以传ephemeral=True,这样后续的followup默认也是临时消息,不用重复传参。
备注:内容来源于stack exchange,提问作者doordashcon
相关产品推荐
相关产品推荐

