Issues with loading cogs in a Python Discord bot and runtime warnings

I’m new to developing Discord bots using Python and I’m facing some challenges when trying to load cogs. Everything works fine in a single file, but I encounter runtime warnings as soon as I implement cogs.

main.py

import discord
import os
from discord.ext import commands
from dotenv import load_dotenv

load_dotenv()
token = os.getenv('TOKEN')

intents = discord.Intents.default()
intents.messages = True
intents.message_content = True

bot = commands.Bot(command_prefix='!', intents=intents)

@bot.event
async def on_ready():
    print("Bot is up and ready!")

@bot.command()
async def load_cog(ctx, cog_name):
    try:
        bot.load_extension(f'cogs.{cog_name}')
        await ctx.send(f'Cog {cog_name} has been loaded.')
    except Exception as e:
        await ctx.send(f'Error loading cog: {e}')

if __name__ == "__main__":
    for filename in os.listdir('./cogs'):
        if filename.endswith('.py'):
            bot.load_extension(f'cogs.{filename[:-3]}')

    bot.run(token)

cogs/sample_game.py

from discord.ext import commands
import random

class SampleGame(commands.Cog):
    def __init__(self, bot):
        self.bot = bot

    @commands.command()
    async def start_game(self, ctx):
        # Game logic goes here
        pass

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

I’m getting runtime warnings that I can’t resolve:

RuntimeWarning: coroutine 'BotBase.load_extension' was never awaited
  bot.load_extension(f'cogs.{filename[:-3]}')
RuntimeWarning: Enable tracemalloc to get the object allocation traceback

What am I doing incorrectly with the cog implementation? The bot connects successfully, but these warnings are concerning me.

You’re mixing sync and async code. The main issue is calling bot.load_extension synchronously before the bot runs, but newer discord.py versions need you to await it. I hit this same problem migrating an older bot. Don’t load cogs in the main block - create an async function that loads all extensions and call it from on_ready. You could use asyncio.run() before starting the bot, but on_ready is cleaner since it waits for full initialization. The tracemalloc warning is just Python suggesting memory debugging tools for the coroutine mess.

Those runtime warnings stem from the changes in discord.py versions. In version 2.0 and above, the method load_extension is now asynchronous, which means it should be awaited. You should move your cog loading logic into the on_ready event so that you can properly use await with bot.load_extension. This adjustment resolves the warnings and allows for better error handling as well since it enables you to manage load failures without crashing the bot. I faced a similar issue during my own upgrade and it took me a while to pinpoint this change.

Same thing happened when I upgraded discord.py. Easy fix - wrap your cog loading in an async setup function and call it with asyncio.run() before bot.run(). Like async def load_cogs(): await bot.load_extension(...) then asyncio.run(load_cogs()) in your main block. Works perfectly.