pythondiscord

Pycord cog loading gives TypeError: object NoneType can't be used in 'await' expression despite using async setup


I'm writing a Discord bot using Pycord, and I'm trying to dynamically load cogs with an async def setup(bot) method.

Here's the relevant part of my main.py:

async def main():
    for filename in os.listdir("cogs"):
        if filename.endswith(".py"):
            cog_path = f"cogs.{filename[:-3]}"
            print(f"πŸ“₯ Importing {cog_path}")
            try:
                module = importlib.import_module(cog_path)
                setup = getattr(module, "setup", None)
                print(f"πŸ” Checking setup in {cog_path}: {setup}")
                print(f"πŸ” Type of setup: {type(setup)}")

                if setup:
                    if inspect.iscoroutinefunction(setup):
                        await setup(bot)
                    else:
                        print(f"⚠️ Skipped setup for {cog_path} because it's not async.")
            except Exception as e:
                print(f"❌ Failed to load {cog_path}: {e.__class__.__name__} - {e}")

    await bot.start(TOKEN)

And here’s the trivia.py cog:

async def setup(bot):
    await bot.add_cog(Trivia(bot))

I get the following error at runtime:

πŸ“₯ Importing cogs.trivia
πŸ” Checking setup in cogs.trivia: <function setup at 0x703c16e92020>
πŸ” Type of setup: <class 'function'>
❌ Failed to load cogs.trivia: TypeError - object NoneType can't be used in 'await' expression

Even though the setup function is async and the cog is implemented correctly. There are more cogs than this all returning the same exact error, some of them work and some do not.

I'm using Pycord Version: 2.6.1 in a WSL environment, not discord.py, and I confirmed that setup is a coroutine function via inspect.iscoroutinefunction(setup).

Questions

  1. Why would I be getting NoneType in await setup(bot) even when it's async?

  2. Is there something different about Pycord's cog loading I should be aware of?


Solution

  • Based on pycord doc add_cog is not async function so you can't use it with await
    because it is normal function which returns None and you have

    result = bot.add_cog(Trivia(bot))  # None
    await result
    

    which finally does

    await None
    

    You could check inspect.iscoroutinefunction(bot.add_cog)

    You have to write it as normal function

    def setup(bot):
        bot.add_cog(Trivia(bot))
    

    and run it as normal function

    if setup:
       setup(bot)  
    

    In discord.py add_cog is async function.

    And this can make problem when you see some code or tutorial
    but it doesn't show if it is for pycord or discord.py (both use import discord).


    Minimal code for test:

    import discord
    import inspect
    
    print('title:', discord.__title__)  # to make sure if it is `pycord` 
                                        # or other module for discord
    
    bot = discord.Bot()
    
    print('bot.add_cog: async:', inspect.iscoroutinefunction(bot.add_cog))
    

    Result:

    title: pycord
    bot.add_cog: async: False