Discord bot encountering RuntimeError: asyncio.run() cannot be called while an event loop is already running

I developed a Python script to create a Discord bot that fetches the public IP address of my Minecraft server and posts it to a specific Discord channel. However, I keep facing the error mentioned in the title and I cannot figure out the cause of it.

import discord
import requests
from discord.ext import commands, tasks

# Replace 'YOUR_BOT_TOKEN' with your actual Discord bot token.
BOT_TOKEN = 'YOUR_BOT_TOKEN'

# Set up intents for the bot
intents = discord.Intents.default()
intents.typing = False
intents.presences = False

# Function to retrieve the IP address
def fetch_ip():
    try:
        response = requests.get('https://api.ipify.org?format=json')
        if response.status_code == 200:
            return response.json()['ip']
    except requests.RequestException as e:
        print(f'Error fetching IP address: {e}')
    return None

# Function to load channel ID
def get_channel_id():
    try:
        with open('channel_id.txt', 'r') as file:
            return int(file.readline())
    except (FileNotFoundError, ValueError):
        return None

def store_channel_id(channel_id):
    with open('channel_id.txt', 'w') as file:
        file.write(str(channel_id))

# Initialize the bot
bot = commands.Bot(command_prefix='!', description='IPNotifier', intents=intents)

# Task to publish the IP address every 12 hours
@tasks.loop(hours=12)
async def publish_ip():
    channel_id = get_channel_id()
    channel = bot.get_channel(channel_id)
    if channel:
        ip_address = fetch_ip()
        if ip_address:
            async for message in channel.history():
                if message.author == bot.user:
                    await message.delete()
                    break
            new_message = await channel.send(f'Current IP address: {ip_address}')
            await new_message.pin()
        else:
            await channel.send('Could not fetch the IP address.')

# Command to set the channel ID
@bot.command()
async def configure_channel(ctx, channel_id: int):
    if not ctx.guild:
        return await ctx.send('This command needs to be executed in a guild.').
    try:
        channel = bot.get_channel(channel_id)
        if not channel:
            raise ValueError
    except ValueError:
        return await ctx.send('Please provide a valid channel ID from this server.')
    store_channel_id(channel_id)
    await ctx.send(f'Channel ID {channel_id} has been set for IPNotifier.')

# Command to refresh the IP address
@bot.command()
async def refresh_ip(ctx):
    channel_id = get_channel_id()
    channel = bot.get_channel(channel_id)
    if channel:
        ip_address = fetch_ip()
        if ip_address:
            async for message in channel.history():
                if message.author == bot.user:
                    await message.delete()
                    break
            updated_message = await channel.send(f'Updated IP address: {ip_address}')
            await updated_message.pin()
        else:
            await channel.send('Could not update the IP address.')

# Event that triggers when the bot is ready
@bot.event
async def on_ready():
    print(f'{bot.user.name} is now connected to Discord!')
    await bot.change_presence(activity=discord.Game(name='Type !help for commands'))
    publish_ip.start()

# Start the bot with the token
bot.run(BOT_TOKEN)

Initially, I was using client.run('[token]'), then switched to bot.run('[token]'), and later followed suggestions to set the BOT_TOKEN at the top. However, the same error keeps occurring.

@Grace_31Dance hey, another thing you could try is using asyncio.get_event_loop() to see if there’s already a running loop. Sometimes, combining the bot with other packages like nest_asyncio can help avoid these RuntimeError if you’re running this outside a regular terminal environmnt. Hope it works!

I encountered a similar issue once when developing a Discord bot on a specific IDE. The issue was that the IDE had its own control over the asyncio event loop, causing conflicts. One fix is to check if you’re running this in an interactive shell like IPython or Jupyter, which manages the loop differently. Another potential solution is to ensure that your code isn’t inadvertently initiating multiple bots or running script commands that invoke nested asyncio loops. Switching to a basic text editor and running the script directly from the terminal resolved the problem in my case.