Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Simple Error Handling for ext.commands - discord.py
"""
If you are not using this inside a cog, add the event decorator e.g:
@bot.event
async def on_command_error(ctx, error)
For examples of cogs see:
https://gist.github.com/EvieePy/d78c061a4798ae81be9825468fe146be
For a list of exceptions:
https://discordpy.readthedocs.io/en/latest/ext/commands/api.html#exceptions
"""
import discord
import traceback
import sys
from discord.ext import commands
class CommandErrorHandler(commands.Cog):
def __init__(self, bot):
self.bot = bot
@commands.Cog.listener()
async def on_command_error(self, ctx, error):
"""The event triggered when an error is raised while invoking a command.
Parameters
------------
ctx: commands.Context
The context used for command invocation.
error: commands.CommandError
The Exception raised.
"""
# This prevents any commands with local handlers being handled here in on_command_error.
if hasattr(ctx.command, 'on_error'):
return
# This prevents any cogs with an overwritten cog_command_error being handled here.
cog = ctx.cog
if cog:
if cog._get_overridden_method(cog.cog_command_error) is not None:
return
ignored = (commands.CommandNotFound, )
# Allows us to check for original exceptions raised and sent to CommandInvokeError.
# If nothing is found. We keep the exception passed to on_command_error.
error = getattr(error, 'original', error)
# Anything in ignored will return and prevent anything happening.
if isinstance(error, ignored):
return
if isinstance(error, commands.DisabledCommand):
await ctx.send(f'{ctx.command} has been disabled.')
elif isinstance(error, commands.NoPrivateMessage):
try:
await ctx.author.send(f'{ctx.command} can not be used in Private Messages.')
except discord.HTTPException:
pass
# For this error example we check to see where it came from...
elif isinstance(error, commands.BadArgument):
if ctx.command.qualified_name == 'tag list': # Check if the command being invoked is 'tag list'
await ctx.send('I could not find that member. Please try again.')
else:
# All other Errors not returned come here. And we can just print the default TraceBack.
print('Ignoring exception in command {}:'.format(ctx.command), file=sys.stderr)
traceback.print_exception(type(error), error, error.__traceback__, file=sys.stderr)
"""Below is an example of a Local Error Handler for our command do_repeat"""
@commands.command(name='repeat', aliases=['mimic', 'copy'])
async def do_repeat(self, ctx, *, inp: str):
"""A simple command which repeats your input!
Parameters
------------
inp: str
The input you wish to repeat.
"""
await ctx.send(inp)
@do_repeat.error
async def do_repeat_handler(self, ctx, error):
"""A local Error Handler for our command do_repeat.
This will only listen for errors in do_repeat.
The global on_command_error will still be invoked after.
"""
# Check if our required argument inp is missing.
if isinstance(error, commands.MissingRequiredArgument):
if error.param.name == 'inp':
await ctx.send("You forgot to give me input to repeat!")
def setup(bot):
bot.add_cog(CommandErrorHandler(bot))
import discord
import traceback
import sys
from discord.ext import commands
class CommandErrorHandler(commands.Cog):
def __init__(self, bot):
self.bot = bot
@commands.Cog.listener()
async def on_command_error(self, ctx, error):
"""The event triggered when an error is raised while invoking a command.
Parameters
------------
ctx: commands.Context
The context used for command invocation.
error: commands.CommandError
The Exception raised.
"""
if hasattr(ctx.command, 'on_error'):
return
cog = ctx.cog
if cog:
if cog._get_overridden_method(cog.cog_command_error) is not None:
return
ignored = (commands.CommandNotFound, )
error = getattr(error, 'original', error)
if isinstance(error, ignored):
return
if isinstance(error, commands.DisabledCommand):
await ctx.send(f'{ctx.command} has been disabled.')
elif isinstance(error, commands.NoPrivateMessage):
try:
await ctx.author.send(f'{ctx.command} can not be used in Private Messages.')
except discord.HTTPException:
pass
elif isinstance(error, commands.BadArgument):
if ctx.command.qualified_name == 'tag list':
await ctx.send('I could not find that member. Please try again.')
else:
print('Ignoring exception in command {}:'.format(ctx.command), file=sys.stderr)
traceback.print_exception(type(error), error, error.__traceback__, file=sys.stderr)
@commands.command(name='repeat', aliases=['mimic', 'copy'])
async def do_repeat(self, ctx, *, inp: str):
"""A simple command which repeats your input!
Parameters
------------
inp: str
The input you wish to repeat.
"""
await ctx.send(inp)
@do_repeat.error
async def do_repeat_handler(self, ctx, error):
"""A local Error Handler for our command do_repeat.
This will only listen for errors in do_repeat.
The global on_command_error will still be invoked after.
"""
if isinstance(error, commands.MissingRequiredArgument):
if error.param.name == 'inp':
await ctx.send("You forgot to give me input to repeat!")
def setup(bot):
bot.add_cog(CommandErrorHandler(bot))
@Modelmat

This comment has been minimized.

Copy link

@Modelmat Modelmat commented Jan 30, 2018

Hey, another example to prevent for the use of on_command_error occurring when __error defined in cogs, use

if hasattr(bot.get_cog(ctx.command.cog_name), '_' + ctx.command.cog_name + '__error'):
        return

Also maybe include __error for in cogs.

@EvieePy

This comment has been minimized.

Copy link
Owner Author

@EvieePy EvieePy commented Mar 2, 2018

@Modelmat

Hey, another example to prevent for the use of on_command_error occurring when __error defined in cogs, use

Since this is probably a niche thing, and slightly confusing to those who are not familiar with name mangling, I will keep it from the actual examples. Though should someone want to add that to the global handler...

if hasattr(ctx.cog, f'_{ctx.cog.__class__.__name__}__error'):
    ...  # Do whatever...

Would be a much simpler way of doing this.

@ClementJ18

This comment has been minimized.

Copy link

@ClementJ18 ClementJ18 commented May 7, 2018

The MissingRequiredArgument if statements need to be updated, I'm not sure what changed, whether it was the shift to rewrite or some update of the inspect lib but error.param is a inspect.Parameter object and therefore will always return false in rewrite when compared to a string.

if error.param == 'inp':

has to be replaced by

if error.param.name == 'inp':
@laggycomputer

This comment has been minimized.

Copy link

@laggycomputer laggycomputer commented Jan 5, 2019

Grammar error on L41.

@jkdz12

This comment has been minimized.

Copy link

@jkdz12 jkdz12 commented Mar 3, 2019

Since 02/23/2019 this Error Handler doesn't work due the cog changes.
So I suggest you to updating:

    @commands.Cog.listener()
    async def on_command_error(self, ctx, error):
class CommandErrorHandler(commands.Cog):
@fleesu

This comment has been minimized.

Copy link

@fleesu fleesu commented Mar 9, 2019

It's an easter egg!

@Moire9

This comment has been minimized.

Copy link

@Moire9 Moire9 commented Aug 10, 2020

What is this licensed under?

@McJoe21

This comment has been minimized.

Copy link

@McJoe21 McJoe21 commented Sep 20, 2020

Grammar error on L41.

That's try:

@justanothernoob4648

This comment has been minimized.

Copy link

@justanothernoob4648 justanothernoob4648 commented Sep 22, 2020

The printing default traceback thing doesn't work

@ghost

This comment has been minimized.

Copy link

@ghost ghost commented Oct 10, 2020

The printing default traceback thing doesn't work

Yeah doesn't work me either

@billyeatcookies

This comment has been minimized.

Copy link

@billyeatcookies billyeatcookies commented Oct 27, 2020

@hello.error
async def hello_error(self, ctx, error):

is it the right way of having arguments

@Shri2007

This comment has been minimized.

Copy link

@Shri2007 Shri2007 commented Feb 22, 2021

mine not working

@ghost

This comment has been minimized.

Copy link

@ghost ghost commented Mar 7, 2021

mine not working

are you gonna give an error? or say what it is doing? or show your source so people can see what you messed up?

@MrKomodoDragon

This comment has been minimized.

Copy link

@MrKomodoDragon MrKomodoDragon commented Apr 19, 2021

could this possibly be updated because command.has_error_handler and cog.has_error_handler exists?

@frogmasta

This comment has been minimized.

Copy link

@frogmasta frogmasta commented Apr 27, 2021

Using these, we can just put this in the main on_command_error():

if ctx.command.has_error_handler() or ctx.cog.has_error_handler():
    return
@Daudd

This comment has been minimized.

Copy link

@Daudd Daudd commented Apr 27, 2021

Using these, we can just put this in the main on_command_error():

if ctx.command.has_error_handler or ctx.cog.has_error_handler:
    return

Isn't it should be has_error_handler()?

@benjamonnguyen

This comment has been minimized.

Copy link

@benjamonnguyen benjamonnguyen commented May 26, 2021

Does anyone know how to handle this error?
'Forbidden: 403 Forbidden (error code: 50001): Missing Access'

@frogmasta

This comment has been minimized.

Copy link

@frogmasta frogmasta commented May 26, 2021

@Daudd yea, you're right. Fixed my code.

@krishna0223

This comment has been minimized.

Copy link

@krishna0223 krishna0223 commented Jul 15, 2021

how to use this in my bot
i mean how to import this

@ImNimboss

This comment has been minimized.

Copy link

@ImNimboss ImNimboss commented Jul 15, 2021

@benjamonnguyen You don't have the right permissions to do whatever you're trying to do

@BSOD2528

This comment has been minimized.

Copy link

@BSOD2528 BSOD2528 commented Oct 5, 2021

how to use this in my bot i mean how to import this

you dont have to import anything to make use of it. just make sure that its in your cogs folder

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment