Discord Bot命令转hybrid command报回调非协程错误排查
Discord.py 混合命令报「回调必须是协程」修复方案
报错核心原因
你在命令函数上同时叠加了@commands.hybrid_command和@app_commands.command()两个装饰器,属于写法错误:
- 装饰器执行顺序为从下往上,
@app_commands.command()会先把原本的协程函数包装成应用命令对象,这个对象本身不是协程。外层的@commands.hybrid_command拿到这个非协程对象做合法性校验时,就会直接抛出「the callback must be a coroutine」错误。 @commands.hybrid_command本身就会同时注册前缀普通命令、斜杠应用命令,不需要额外再加@app_commands.command()装饰器。
另外你的代码还有两处隐性问题:
- hybrid命令第一个入参要求是
commands.Context类型,你写的discord.Interaction不符合签名规范,会导致前缀命令触发时参数解析错误。 main.py的__init__方法中,你提前配置了开启message_content权限的intents,但传给父类构造函数时又新建了一个discord.Intents.all(),之前的配置没有生效;setup_hook里同步命令树用了全局变量bot,类内部应该用self指代实例,会触发变量未定义错误。
修复方案
- 删除
help命令上多余的@app_commands.command()装饰器 - 修正hybrid命令的入参签名,适配两种调用方式的响应逻辑
- 修正
main.py里的intents传参、tree.sync调用对象错误
修复后 main.py 代码
class MyBot(commands.Bot): def __init__(self): intents=discord.Intents.all() intents.message_content = True super().__init__( command_prefix='!', intents=intents # 传入提前配置好权限的intents ) self.initial_extensions = [ "cogs.user_commands" ] async def setup_hook(self): for ext in self.initial_extensions: await self.load_extension(ext) # 类内部用self指代当前bot实例 await self.tree.sync(guild = discord.Object(id=191453821174531128))
修复后 cogs/user_commands.py 代码
from typing import Optional, List import discord from discord import app_commands from discord.ext import commands class user_commands(commands.Cog): def __init__(self, bot): self.bot = bot bot.remove_command("help") @commands.hybrid_command(name='help', with_app_command=True, description='查看命令帮助') async def help(self, ctx: commands.Context, command: Optional[str]): # 原有embed生成逻辑保留 ...... # 兼容两种触发方式的响应逻辑 if ctx.interaction: # 斜杠触发时返回临时消息 await ctx.send(embed=embed, ephemeral=True) else: # 前缀命令触发时返回普通频道消息 await ctx.send(embed=embed) @help.autocomplete('command') async def help_autocomplete(self, interaction: discord.Interaction, current: str, ) -> List[app_commands.Choice[str]]: # 原有自动补全逻辑保留 .....
补充注意
- 如果你需要给hybrid命令的斜杠版本添加参数说明,可以直接用
@app_commands.describe()装饰器,不要重复叠加@app_commands.command()。 - 写完修改后重启bot,第一次同步斜杠命令可能需要1-2分钟生效,测试时不要频繁调用sync接口避免触发接口限流。
内容的提问来源于stack exchange,提问作者DeadPool
相关产品推荐
相关产品推荐

