Bot joins and plays music but after disconnecting and rejoining it says 'Bot not connected to voice'

Viewed 213

So basically after rythm and groovy shutting down I decided to make my own music bot. My bot works perfectly but every time I play a song in the first run and when I make it disconnect and connect back the bot is in the voice channel but when i do discord.ext.commands.errors.CommandInvokeError: Command raised an exception: ClientException: Not connected to voice. And I wanted to know if any of y'all knew how to fix it, Thanks!

My bot code:

import discord
from discord.ext import commands
from discord.ext import tasks
import nacl
import DiscordUtils
import random
import asyncio


sm = commands.Bot(command_prefix = "sm ", help_command=None, intents = discord.Intents().all())
music = DiscordUtils.Music()

@sm.event
async def on_ready():
  print('We have logged in as {0.user}'.format(sm))

async def ch_pr():
    await sm.wait_until_ready()

    statuses = ["Work In Progress", "Music Bot", "Beta Stage"]

    while not sm.is_closed():
        status = random.choice(statuses)
        await sm.change_presence(status=discord.Status.idle,activity=discord.Game(name=status))
        await asyncio.sleep(10)

sm.loop.create_task(ch_pr())

@sm.command()
async def join(ctx):
    voicetrue = ctx.author.voice
    if voicetrue is None:
        embedVar=discord.Embed(color=0x70cfff)
        embedVar.set_author(name=ctx.message.author.name, icon_url=ctx.message.author.avatar_url)
        embedVar.add_field(name=":no_entry_sign: | Error! You are not in a voice channel!", value="-----------------------------")
        return await ctx.send(embed=embedVar)

    await ctx.author.voice.channel.connect()

@sm.command()
async def leave(ctx):
    voicetrue = ctx.author.voice
    mevoicetrue = ctx.guild.me.voice
    player = music.get_player(guild_id=ctx.guild.id)
    if voicetrue is None:
        embedVar=discord.Embed(color=0x70cfff)
        embedVar.set_author(name=ctx.message.author.name, icon_url=ctx.message.author.avatar_url)
        embedVar.add_field(name=":no_entry_sign: | Error! You are not in a voice channel!", value="-----------------------------")
        return await ctx.send(embed=embedVar)
    if mevoicetrue is None:
        embedVar=discord.Embed(color=0x70cfff)
        embedVar.set_author(name=ctx.message.author.name, icon_url=ctx.message.author.avatar_url)
        embedVar.add_field(name=":no_entry_sign: | Error! I am not connected to a voice channel!", value="-----------------------------")
        return await ctx.send(embed=embedVar)
    
    if ctx.message.author.voice:
        channel = ctx.message.author.voice.channel
        server = ctx.message.guild.voice_client
        await server.disconnect()

@sm.command()
async def play(ctx, *, url):
    player = music.get_player(guild_id=ctx.guild.id)
    
    if not player:
        player = music.create_player(ctx, ffmpeg_error_betterfix=True)

    if not ctx.voice_client.is_playing():
        await player.queue(url, search=True)
        song = await player.play()
        embedVar=discord.Embed(color=0x70cfff)
        embedVar.set_author(name=ctx.message.author.name, icon_url=ctx.message.author.avatar_url)
        embedVar.add_field(name=f":arrow_forward: | Playing {song.name}", value="-----------------------------")
        await ctx.send(embed=embedVar)
    else:
        song = await player.queue(url, search=True)
        embedVar=discord.Embed(color=0x70cfff)
        embedVar.set_author(name=ctx.message.author.name, icon_url=ctx.message.author.avatar_url)
        embedVar.add_field(name=f":white_check_mark: | {song.name} has been added to the queue!", value="----------------------------")
        await ctx.send(embed=embedVar)

@sm.command()
async def queue(ctx):
    player = music.get_player(guild_id=ctx.guild.id)
    embedVar=discord.Embed(color=0x70cfff)
    embedVar.set_author(name=ctx.message.author.name, icon_url=ctx.message.author.avatar_url)
    embedVar.add_field(name=f"{', '.join([song.name for song in player.current_queue()])}", value="----------------------------")
    await ctx.send(embed=embedVar)

@sm.command()
async def pause(ctx):
    player = music.get_player(guild_id=ctx.guild.id)
    song = await player.pause()
    embedVar=discord.Embed(color=0x70cfff)
    embedVar.set_author(name=ctx.message.author.name, icon_url=ctx.message.author.avatar_url)
    embedVar.add_field(name=f":pause_button: | {song.name} has been paused!", value="----------------------------")
    await ctx.send(embed=embedVar)

@sm.command()
async def resume(ctx):
    player = music.get_player(guild_id=ctx.guild.id)
    song = await player.resume()
    embedVar=discord.Embed(color=0x70cfff)
    embedVar.set_author(name=ctx.message.author.name, icon_url=ctx.message.author.avatar_url)
    embedVar.add_field(name=f":arrow_forward: | Resuming {song.name}!", value="----------------------------")
    await ctx.send(embed=embedVar)

@sm.command()
async def loop(ctx):
    player = music.get_player(guild_id=ctx.guild.id)
    song = await player.toggle_song_loop()
    if song.is_looping:
        embedVar=discord.Embed(color=0x70cfff)
        embedVar.set_author(name=ctx.message.author.name, icon_url=ctx.message.author.avatar_url)
        embedVar.add_field(name=f":repeat: | {song.name} is now looping!", value="----------------------------")
        await ctx.send(embed=embedVar)
    else:
        embedVar=discord.Embed(color=0x70cfff)
        embedVar.set_author(name=ctx.message.author.name, icon_url=ctx.message.author.avatar_url)
        embedVar.add_field(name=f":no_entry_sign: | Error! {song.name} is not looping!", value="----------------------------")
        await ctx.send(embed=embedVar)

@sm.command()
async def np(ctx):
    player = music.get_player(guild_id=ctx.guild.id)
    embedVar=discord.Embed(color=0x70cfff)
    embedVar.set_author(name=ctx.message.author.name, icon_url=ctx.message.author.avatar_url)
    embedVar.add_field(name=f":arrow_forward: | {player.now_playing().name} is currently playing!", value="----------------------------")
    await ctx.send(embed=embedVar)

@sm.command()
async def remove(ctx, index):
    player = music.get_player(guild_id=ctx.guild.id)
    song = await player.remove_from_queue(int(index))
    embedVar=discord.Embed(color=0x70cfff)
    embedVar.set_author(name=ctx.message.author.name, icon_url=ctx.message.author.avatar_url)
    embedVar.add_field(name=f":white_check_mark: | {song.name} has been removed from queue!", value="----------------------------")
    await ctx.send(embed=embedVar)

@sm.command()
async def skip(ctx):
    player = music.get_player(guild_id=ctx.guild.id)
    song = await player.skip(force=True)
    if len(song) == 2:
        embedVar=discord.Embed(color=0x70cfff)
        embedVar.set_author(name=ctx.message.author.name, icon_url=ctx.message.author.avatar_url)
        embedVar.add_field(name=f":white_check_mark: | {song[0].name} has been skipped to {song[1].name}!", value="----------------------------")
        await ctx.send(embed=embedVar)
    else:
        embedVar=discord.Embed(color=0x70cfff)
        embedVar.set_author(name=ctx.message.author.name, icon_url=ctx.message.author.avatar_url)
        embedVar.add_field(name=f":white_check_mark: | {song.name} has been skipped!", value="----------------------------")
        await ctx.send(embed=embedVar)

 #help command

@sm.command()
async def help(ctx):
    embedVar=discord.Embed(color=0x70cfff)
    embedVar.set_author(name="Command List", icon_url=ctx.message.author.avatar_url)
    embedVar.add_field(name="**sm join**", value="Joins the voice channel (Required for playing music)", inline=True)
    embedVar.add_field(name="**sm play**", value="Searches for a song name or plays a youtube link", inline=False)
    embedVar.add_field(name="**sm pause**", value="Pauses a song", inline=False)
    embedVar.add_field(name="**sm resume**", value="Resumes a song", inline=False)
    embedVar.add_field(name="**sm skip**", value="Skips the current song", inline=False)
    embedVar.add_field(name="**sm queue**", value="Shows the songs in queue", inline=False)
    embedVar.add_field(name="**sm remove**", value="Removes a song from queue", inline=False)
    embedVar.add_field(name="**sm np**", value="Shows the now playing song", inline=False)
    embedVar.add_field(name="**sm loop**", value="Loops the current song", inline=False)
    embedVar.add_field(name="**sm pause**", value="Pauses a song", inline=False)
    embedVar.add_field(name="**sm leave**", value="Leaves the voice channel", inline=False)
    await ctx.send(embed=embedVar)

sm.run('Token')

Error Code:

Ignoring exception in command play:
Traceback (most recent call last):
  File "/home/container/.local/lib/python3.9/site-packages/discord/ext/commands/core.py", line 85, in wrapped
    ret = await coro(*args, **kwargs)
  File "/home/container/senmusic.py", line 70, in play
    song = await player.play()
  File "/home/container/.local/lib/python3.9/site-packages/DiscordUtils/Music.py", line 197, in play
    self.voice.play(source, after=lambda error: self.after_func(self.ctx, self.ffmpeg_opts, self.music, self.after_func, self.on_play_func, self.loop))
  File "/home/container/.local/lib/python3.9/site-packages/discord/voice_client.py", line 555, in play
    raise ClientException('Not connected to voice.')
discord.errors.ClientException: Not connected to voice.

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/container/.local/lib/python3.9/site-packages/discord/ext/commands/bot.py", line 939, in invoke
    await ctx.command.invoke(ctx)
  File "/home/container/.local/lib/python3.9/site-packages/discord/ext/commands/core.py", line 863, in invoke
    await injected(*ctx.args, **ctx.kwargs)
  File "/home/container/.local/lib/python3.9/site-packages/discord/ext/commands/core.py", line 94, in wrapped
    raise CommandInvokeError(exc) from exc
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: ClientException: Not connected to voice.
1 Answers

Using ctx.message.guild.voice_client.disconnect() does not destroy the player object created by music.create_player(ctx, ffmpeg_error_betterfix=True).

This means that when you try to play something after the bot has disconnected and connected to a voice channel, it will attempt to use the old player object which is no longer valid, even if the bot connects to the same voice channel.

Checking the source code for DiscordUtils.Music, there are two methods that you can use to destroy player, either player.disable() or player.delete().

@sm.command()
async def leave(ctx):
    voicetrue = ctx.author.voice
    mevoicetrue = ctx.guild.me.voice
    player = music.get_player(guild_id=ctx.guild.id)
    if voicetrue is None:
        embedVar=discord.Embed(color=0x70cfff)
        embedVar.set_author(name=ctx.message.author.name, icon_url=ctx.message.author.avatar_url)
        embedVar.add_field(name=":no_entry_sign: | Error! You are not in a voice channel!", value="-----------------------------")
        return await ctx.send(embed=embedVar)
    if mevoicetrue is None:
        embedVar=discord.Embed(color=0x70cfff)
        embedVar.set_author(name=ctx.message.author.name, icon_url=ctx.message.author.avatar_url)
        embedVar.add_field(name=":no_entry_sign: | Error! I am not connected to a voice channel!", value="-----------------------------")
        return await ctx.send(embed=embedVar)
    
    if ctx.message.author.voice:
        channel = ctx.message.author.voice.channel
        server = ctx.message.guild.voice_client
        await server.disconnect()

        player = music.get_player(guild_id=ctx.guild.id)
        player.disable()
Related