Skip to content

Error Handling

Shows both per-command error handlers and a global error handler, covering argument validation, runtime errors, and unknown commands.

from matrix import Bot, Context
from matrix.errors import CommandNotFoundError, MissingArgumentError

bot = Bot()


@bot.error(CommandNotFoundError)
async def global_error(error: CommandNotFoundError) -> None:
    print(f"Global error handler {error}.")


@bot.command("div")
async def division(ctx: Context, a: int, b: int) -> None:
    c = a / b
    await ctx.reply(f"{a} / {b} = {c}")


@division.error(ZeroDivisionError)
async def div_error(ctx: Context, error: ZeroDivisionError) -> None:
    await ctx.reply(f"Operation not allowed: {error}")


@division.error(ValueError)
async def val_error(ctx: Context, error: ValueError) -> None:
    await ctx.reply(f"ValueError: {error}")


@division.error(MissingArgumentError)
async def command_error(ctx: Context, error: MissingArgumentError) -> None:
    await ctx.reply(f"{error}")


bot.start(config="config.yaml")

Three layers of error handling are demonstrated:

  • Global handler@bot.error(CommandNotFoundError) catches any command the bot doesn't recognise, across the whole bot. No ctx is available here since no command was matched.
  • Per-command handlers@division.error(ZeroDivisionError) and @division.error(ValueError) handle errors raised inside the division function itself.
  • Argument handler@division.error(MissingArgumentError) fires when the user doesn't supply enough arguments.

Handlers are matched by exception type. If no handler is registered for a raised exception, it propagates normally.

See the Error Handling guide for the full picture.