0
# Error Handling and Exceptions
1
2
Comprehensive exception hierarchy for handling Discord API errors, connection issues, command errors, and other failure scenarios. This system provides detailed error information and proper exception handling patterns for robust Discord bot development.
3
4
## Capabilities
5
6
### Core Discord Exceptions
7
8
Base exception classes for Discord-related errors and API failures.
9
10
```python { .api }
11
class DiscordException(Exception):
12
"""
13
Base exception class for Discord-related errors.
14
15
All discord.py exceptions inherit from this class.
16
"""
17
pass
18
19
class ClientException(DiscordException):
20
"""
21
Exception raised for client-side errors.
22
23
These are errors caused by incorrect usage of the library
24
rather than Discord API issues.
25
"""
26
pass
27
28
class NoMoreItems(DiscordException):
29
"""
30
Exception raised when an async iterator has no more items.
31
"""
32
pass
33
34
class GatewayNotFound(DiscordException):
35
"""
36
Exception raised when the Discord gateway endpoint is not found.
37
"""
38
pass
39
40
class ConnectionClosed(DiscordException):
41
"""
42
Exception raised when the gateway connection is closed unexpectedly.
43
"""
44
45
def __init__(self, original: Exception, shard_id: Optional[int] = None) -> None:
46
"""
47
Initialize connection closed exception.
48
49
Parameters:
50
- original: Exception - The original exception that caused the closure
51
- shard_id: int - ID of the shard that disconnected
52
"""
53
54
@property
55
def code(self) -> int:
56
"""The WebSocket close code."""
57
58
@property
59
def reason(self) -> str:
60
"""The reason for the connection closure."""
61
62
@property
63
def shard_id(self) -> Optional[int]:
64
"""The shard ID that disconnected."""
65
66
class PrivilegedIntentsRequired(ClientException):
67
"""
68
Exception raised when privileged intents are required but not enabled.
69
70
This occurs when trying to access features that require privileged intents
71
(message content, members, presences) without having them enabled.
72
"""
73
74
def __init__(self, shard_id: Optional[int] = None) -> None: ...
75
76
@property
77
def shard_id(self) -> Optional[int]: ...
78
79
class LoginFailure(DiscordException):
80
"""
81
Exception raised when bot login fails.
82
83
Usually caused by invalid bot token.
84
"""
85
pass
86
```
87
88
### HTTP and API Exceptions
89
90
Exceptions related to Discord's REST API and HTTP requests.
91
92
```python { .api }
93
class HTTPException(DiscordException):
94
"""
95
Base exception for HTTP-related errors with Discord's API.
96
"""
97
98
def __init__(
99
self,
100
response: aiohttp.ClientResponse,
101
message: Union[str, Dict[str, Any]]
102
) -> None: ...
103
104
@property
105
def response(self) -> aiohttp.ClientResponse:
106
"""The HTTP response that caused the exception."""
107
108
@property
109
def status(self) -> int:
110
"""HTTP status code."""
111
112
@property
113
def code(self) -> int:
114
"""Discord API error code."""
115
116
@property
117
def text(self) -> str:
118
"""Error message text."""
119
120
class Forbidden(HTTPException):
121
"""
122
Exception raised for 403 Forbidden HTTP responses.
123
124
Indicates insufficient permissions for the requested action.
125
"""
126
pass
127
128
class NotFound(HTTPException):
129
"""
130
Exception raised for 404 Not Found HTTP responses.
131
132
Indicates the requested resource doesn't exist.
133
"""
134
pass
135
136
class DiscordServerError(HTTPException):
137
"""
138
Exception raised for 5xx server error HTTP responses.
139
140
Indicates an error on Discord's side.
141
"""
142
pass
143
144
class InvalidData(DiscordException):
145
"""
146
Exception raised when Discord sends invalid or unexpected data.
147
"""
148
pass
149
150
class InvalidArgument(DiscordException):
151
"""
152
Exception raised when an invalid argument is passed to a function.
153
"""
154
pass
155
156
class ValidationError(DiscordException):
157
"""
158
Exception raised when data validation fails.
159
"""
160
pass
161
```
162
163
### Extension Management Exceptions
164
165
Exceptions related to loading and managing bot extensions and cogs.
166
167
```python { .api }
168
class ExtensionError(DiscordException):
169
"""
170
Base exception for extension-related errors.
171
"""
172
173
def __init__(self, message: str = None, *, name: str) -> None:
174
"""
175
Initialize extension error.
176
177
Parameters:
178
- message: str - Error message
179
- name: str - Extension name that caused the error
180
"""
181
182
@property
183
def name(self) -> str:
184
"""The name of the extension that caused the error."""
185
186
class ExtensionAlreadyLoaded(ExtensionError):
187
"""
188
Exception raised when trying to load an already loaded extension.
189
"""
190
pass
191
192
class ExtensionNotLoaded(ExtensionError):
193
"""
194
Exception raised when trying to reload/unload an extension that isn't loaded.
195
"""
196
pass
197
198
class NoEntryPointError(ExtensionError):
199
"""
200
Exception raised when an extension doesn't have a setup function.
201
202
Extensions must have either a 'setup' function or a 'Cog' class.
203
"""
204
pass
205
206
class ExtensionFailed(ExtensionError):
207
"""
208
Exception raised when an extension fails to load due to an error.
209
"""
210
211
def __init__(
212
self,
213
name: str,
214
original: Exception
215
) -> None:
216
"""
217
Initialize extension failed error.
218
219
Parameters:
220
- name: str - Extension name
221
- original: Exception - The original exception that caused the failure
222
"""
223
224
@property
225
def original(self) -> Exception:
226
"""The original exception that caused the extension to fail."""
227
228
class ExtensionNotFound(ExtensionError):
229
"""
230
Exception raised when an extension file cannot be found.
231
"""
232
pass
233
```
234
235
### Application Command Exceptions
236
237
Exceptions specific to application commands (slash commands, context menus).
238
239
```python { .api }
240
class ApplicationCommandError(DiscordException):
241
"""
242
Base exception for application command errors.
243
"""
244
pass
245
246
class ApplicationCommandInvokeError(ApplicationCommandError):
247
"""
248
Exception raised when an application command raises an unhandled error.
249
"""
250
251
def __init__(self, command: ApplicationCommand, original: Exception) -> None:
252
"""
253
Initialize command invoke error.
254
255
Parameters:
256
- command: ApplicationCommand - The command that failed
257
- original: Exception - The original exception
258
"""
259
260
@property
261
def command(self) -> ApplicationCommand:
262
"""The command that caused the error."""
263
264
@property
265
def original(self) -> Exception:
266
"""The original exception that was raised."""
267
268
class CheckFailure(ApplicationCommandError):
269
"""
270
Exception raised when an application command check fails.
271
"""
272
pass
273
274
class InteractionResponded(ApplicationCommandError):
275
"""
276
Exception raised when trying to respond to an already responded interaction.
277
"""
278
279
def __init__(self, interaction: Interaction) -> None: ...
280
281
@property
282
def interaction(self) -> Interaction: ...
283
```
284
285
### Command Framework Exceptions (discord.ext.commands)
286
287
Extensive exception system for the commands extension framework.
288
289
```python { .api }
290
# Base Command Errors
291
class CommandError(DiscordException):
292
"""
293
Base exception for command-related errors in the commands extension.
294
"""
295
296
def __init__(self, message: str = None, *args) -> None: ...
297
298
class UserInputError(CommandError):
299
"""
300
Base exception for errors caused by user input.
301
"""
302
pass
303
304
class CommandNotFound(CommandError):
305
"""
306
Exception raised when a command is not found.
307
"""
308
pass
309
310
class MissingRequiredArgument(UserInputError):
311
"""
312
Exception raised when a required command argument is missing.
313
"""
314
315
def __init__(self, param: inspect.Parameter) -> None:
316
"""
317
Initialize missing argument error.
318
319
Parameters:
320
- param: Parameter - The missing parameter
321
"""
322
323
@property
324
def param(self) -> inspect.Parameter:
325
"""The missing parameter."""
326
327
class TooManyArguments(UserInputError):
328
"""
329
Exception raised when too many arguments are provided to a command.
330
"""
331
pass
332
333
class BadArgument(UserInputError):
334
"""
335
Exception raised when argument conversion fails.
336
"""
337
pass
338
339
class ArgumentParsingError(UserInputError):
340
"""
341
Exception raised when argument parsing fails.
342
"""
343
pass
344
345
class UnexpectedQuoteError(ArgumentParsingError):
346
"""
347
Exception raised when an unexpected quote character is found.
348
"""
349
350
def __init__(self, quote: str) -> None: ...
351
352
@property
353
def quote(self) -> str: ...
354
355
class InvalidEndOfQuotedStringError(ArgumentParsingError):
356
"""
357
Exception raised when a quoted string doesn't end properly.
358
"""
359
360
def __init__(self, char: str) -> None: ...
361
362
@property
363
def char(self) -> str: ...
364
365
class ExpectedClosingQuoteError(ArgumentParsingError):
366
"""
367
Exception raised when a closing quote is expected but not found.
368
"""
369
370
def __init__(self, close_quote: str) -> None: ...
371
372
@property
373
def close_quote(self) -> str: ...
374
375
# Check Failures
376
class CheckFailure(CommandError):
377
"""
378
Exception raised when a command check fails.
379
"""
380
pass
381
382
class CheckAnyFailure(CheckFailure):
383
"""
384
Exception raised when all checks in a check_any decorator fail.
385
"""
386
387
def __init__(self, checks: List[Callable], errors: List[CheckFailure]) -> None: ...
388
389
@property
390
def checks(self) -> List[Callable]: ...
391
@property
392
def errors(self) -> List[CheckFailure]: ...
393
394
class PrivateMessageOnly(CheckFailure):
395
"""
396
Exception raised when a command can only be used in private messages.
397
"""
398
pass
399
400
class NoPrivateMessage(CheckFailure):
401
"""
402
Exception raised when a command cannot be used in private messages.
403
"""
404
pass
405
406
class NotOwner(CheckFailure):
407
"""
408
Exception raised when a command requires the user to be the bot owner.
409
"""
410
pass
411
412
class MissingRole(CheckFailure):
413
"""
414
Exception raised when a user is missing a required role.
415
"""
416
417
def __init__(self, missing_role: Union[str, int]) -> None: ...
418
419
@property
420
def missing_role(self) -> Union[str, int]: ...
421
422
class BotMissingRole(CheckFailure):
423
"""
424
Exception raised when the bot is missing a required role.
425
"""
426
427
def __init__(self, missing_role: Union[str, int]) -> None: ...
428
429
@property
430
def missing_role(self) -> Union[str, int]: ...
431
432
class MissingAnyRole(CheckFailure):
433
"""
434
Exception raised when a user is missing all required roles.
435
"""
436
437
def __init__(self, missing_roles: List[Union[str, int]]) -> None: ...
438
439
@property
440
def missing_roles(self) -> List[Union[str, int]]: ...
441
442
class BotMissingAnyRole(CheckFailure):
443
"""
444
Exception raised when the bot is missing all required roles.
445
"""
446
447
def __init__(self, missing_roles: List[Union[str, int]]) -> None: ...
448
449
@property
450
def missing_roles(self) -> List[Union[str, int]]: ...
451
452
class MissingPermissions(CheckFailure):
453
"""
454
Exception raised when a user is missing required permissions.
455
"""
456
457
def __init__(self, missing_permissions: List[str], *args) -> None: ...
458
459
@property
460
def missing_permissions(self) -> List[str]: ...
461
462
class BotMissingPermissions(CheckFailure):
463
"""
464
Exception raised when the bot is missing required permissions.
465
"""
466
467
def __init__(self, missing_permissions: List[str], *args) -> None: ...
468
469
@property
470
def missing_permissions(self) -> List[str]: ...
471
472
class NSFWChannelRequired(CheckFailure):
473
"""
474
Exception raised when a command requires an NSFW channel.
475
"""
476
477
def __init__(self, channel: GuildChannel) -> None: ...
478
479
@property
480
def channel(self) -> GuildChannel: ...
481
482
# Command Execution Errors
483
class DisabledCommand(CommandError):
484
"""
485
Exception raised when a disabled command is invoked.
486
"""
487
pass
488
489
class CommandInvokeError(CommandError):
490
"""
491
Exception raised when a command raises an unhandled exception.
492
"""
493
494
def __init__(self, command: Command, original: Exception) -> None: ...
495
496
@property
497
def command(self) -> Command: ...
498
@property
499
def original(self) -> Exception: ...
500
501
class CommandOnCooldown(CommandError):
502
"""
503
Exception raised when a command is on cooldown.
504
"""
505
506
def __init__(
507
self,
508
cooldown: Cooldown,
509
retry_after: float,
510
type: BucketType
511
) -> None: ...
512
513
@property
514
def cooldown(self) -> Cooldown: ...
515
@property
516
def retry_after(self) -> float: ...
517
@property
518
def type(self) -> BucketType: ...
519
520
class MaxConcurrencyReached(CommandError):
521
"""
522
Exception raised when a command's max concurrency is reached.
523
"""
524
525
def __init__(self, number: int, per: BucketType) -> None: ...
526
527
@property
528
def number(self) -> int: ...
529
@property
530
def per(self) -> BucketType: ...
531
532
# Conversion Errors
533
class ConversionError(CommandError):
534
"""
535
Base exception for argument conversion errors.
536
"""
537
538
def __init__(self, converter: Any, original: Exception) -> None: ...
539
540
@property
541
def converter(self) -> Any: ...
542
@property
543
def original(self) -> Exception: ...
544
545
class BadUnionArgument(UserInputError):
546
"""
547
Exception raised when a Union converter fails.
548
"""
549
550
def __init__(
551
self,
552
param: inspect.Parameter,
553
converters: Tuple[Type, ...],
554
errors: List[CommandError]
555
) -> None: ...
556
557
@property
558
def param(self) -> inspect.Parameter: ...
559
@property
560
def converters(self) -> Tuple[Type, ...]: ...
561
@property
562
def errors(self) -> List[CommandError]: ...
563
564
class BadLiteralArgument(UserInputError):
565
"""
566
Exception raised when a Literal converter fails.
567
"""
568
569
def __init__(
570
self,
571
param: inspect.Parameter,
572
literals: Tuple[Any, ...],
573
argument: str
574
) -> None: ...
575
576
@property
577
def param(self) -> inspect.Parameter: ...
578
@property
579
def literals(self) -> Tuple[Any, ...]: ...
580
@property
581
def argument(self) -> str: ...
582
583
class BadBoolArgument(BadArgument):
584
"""
585
Exception raised when a boolean conversion fails.
586
"""
587
588
def __init__(self, argument: str) -> None: ...
589
590
@property
591
def argument(self) -> str: ...
592
593
class BadColourArgument(BadArgument):
594
"""
595
Exception raised when a Colour conversion fails.
596
"""
597
598
def __init__(self, argument: str) -> None: ...
599
600
@property
601
def argument(self) -> str: ...
602
603
class BadColorArgument(BadColourArgument):
604
"""
605
Alias for BadColourArgument using American spelling.
606
"""
607
pass
608
609
class BadInviteArgument(BadArgument):
610
"""
611
Exception raised when an Invite conversion fails.
612
"""
613
pass
614
615
# Object Not Found Errors
616
class ObjectNotFound(BadArgument):
617
"""
618
Base exception for when a Discord object is not found.
619
"""
620
621
def __init__(self, argument: str) -> None: ...
622
623
@property
624
def argument(self) -> str: ...
625
626
class MessageNotFound(ObjectNotFound):
627
"""
628
Exception raised when a Message is not found.
629
"""
630
pass
631
632
class MemberNotFound(ObjectNotFound):
633
"""
634
Exception raised when a Member is not found.
635
"""
636
pass
637
638
class GuildNotFound(ObjectNotFound):
639
"""
640
Exception raised when a Guild is not found.
641
"""
642
pass
643
644
class UserNotFound(ObjectNotFound):
645
"""
646
Exception raised when a User is not found.
647
"""
648
pass
649
650
class ChannelNotFound(ObjectNotFound):
651
"""
652
Exception raised when a Channel is not found.
653
"""
654
pass
655
656
class ThreadNotFound(ObjectNotFound):
657
"""
658
Exception raised when a Thread is not found.
659
"""
660
pass
661
662
class ChannelNotReadable(ObjectNotFound):
663
"""
664
Exception raised when a channel cannot be read.
665
"""
666
pass
667
668
class RoleNotFound(ObjectNotFound):
669
"""
670
Exception raised when a Role is not found.
671
"""
672
pass
673
674
class EmojiNotFound(ObjectNotFound):
675
"""
676
Exception raised when an Emoji is not found.
677
"""
678
pass
679
680
class GuildStickerNotFound(ObjectNotFound):
681
"""
682
Exception raised when a GuildSticker is not found.
683
"""
684
pass
685
686
class PartialEmojiConversionFailure(ObjectNotFound):
687
"""
688
Exception raised when a PartialEmoji conversion fails.
689
"""
690
pass
691
692
# Flag Argument Errors
693
class FlagError(BadArgument):
694
"""
695
Base exception for flag parsing errors.
696
"""
697
pass
698
699
class BadFlagArgument(FlagError):
700
"""
701
Exception raised when a flag argument is invalid.
702
"""
703
704
def __init__(self, flag: Flag) -> None: ...
705
706
@property
707
def flag(self) -> Flag: ...
708
709
class MissingFlagArgument(FlagError):
710
"""
711
Exception raised when a flag argument is missing.
712
"""
713
714
def __init__(self, flag: Flag) -> None: ...
715
716
@property
717
def flag(self) -> Flag: ...
718
719
class TooManyFlags(FlagError):
720
"""
721
Exception raised when too many flag arguments are provided.
722
"""
723
724
def __init__(self, flag: Flag, values: List[str]) -> None: ...
725
726
@property
727
def flag(self) -> Flag: ...
728
@property
729
def values(self) -> List[str]: ...
730
731
class MissingRequiredFlag(FlagError):
732
"""
733
Exception raised when a required flag is not provided.
734
"""
735
736
def __init__(self, flag: Flag) -> None: ...
737
738
@property
739
def flag(self) -> Flag: ...
740
741
# Command Registration Errors
742
class CommandRegistrationError(ClientException):
743
"""
744
Exception raised when command registration fails.
745
"""
746
pass
747
```
748
749
### Audio and Voice Exceptions
750
751
Exceptions related to voice connections and audio processing.
752
753
```python { .api }
754
class OpusError(DiscordException):
755
"""
756
Base exception for Opus codec errors.
757
"""
758
pass
759
760
class OpusNotLoaded(OpusError):
761
"""
762
Exception raised when Opus library is not available.
763
764
This occurs when trying to use voice features without the Opus codec installed.
765
"""
766
pass
767
```
768
769
### Audio Sink Exceptions
770
771
Exceptions for audio recording and sink operations.
772
773
```python { .api }
774
class SinkException(DiscordException):
775
"""
776
Base exception for audio sink errors.
777
"""
778
pass
779
780
class RecordingException(SinkException):
781
"""
782
Exception raised during audio recording operations.
783
"""
784
pass
785
786
class MP3SinkError(SinkException):
787
"""
788
Exception raised for MP3 audio sink errors.
789
"""
790
pass
791
792
class MP4SinkError(SinkException):
793
"""
794
Exception raised for MP4 audio sink errors.
795
"""
796
pass
797
798
class OGGSinkError(SinkException):
799
"""
800
Exception raised for OGG audio sink errors.
801
"""
802
pass
803
804
class MKVSinkError(SinkException):
805
"""
806
Exception raised for MKV audio sink errors.
807
"""
808
pass
809
810
class WaveSinkError(SinkException):
811
"""
812
Exception raised for WAV audio sink errors.
813
"""
814
pass
815
816
class M4ASinkError(SinkException):
817
"""
818
Exception raised for M4A audio sink errors.
819
"""
820
pass
821
822
class MKASinkError(SinkException):
823
"""
824
Exception raised for MKA audio sink errors.
825
"""
826
pass
827
828
class OggError(DiscordException):
829
"""
830
Exception raised for OGG file parsing errors.
831
"""
832
pass
833
```
834
835
### Error Handling Patterns
836
837
Common patterns and best practices for handling errors in py-cord applications.
838
839
```python
840
# Example: Basic Error Handling
841
@bot.event
842
async def on_application_command_error(ctx, error):
843
if isinstance(error, discord.Forbidden):
844
await ctx.respond("I don't have permission to do that!", ephemeral=True)
845
elif isinstance(error, discord.NotFound):
846
await ctx.respond("That resource wasn't found.", ephemeral=True)
847
elif isinstance(error, discord.HTTPException):
848
await ctx.respond(f"An HTTP error occurred: {error.text}", ephemeral=True)
849
else:
850
# Log unexpected errors
851
print(f"Unexpected error: {error}")
852
await ctx.respond("An unexpected error occurred.", ephemeral=True)
853
854
# Example: Command Extension Error Handling
855
@bot.event
856
async def on_command_error(ctx, error):
857
if isinstance(error, commands.CommandNotFound):
858
return # Ignore command not found
859
elif isinstance(error, commands.MissingRequiredArgument):
860
await ctx.send(f"Missing argument: {error.param.name}")
861
elif isinstance(error, commands.BadArgument):
862
await ctx.send("Invalid argument provided.")
863
elif isinstance(error, commands.CommandOnCooldown):
864
await ctx.send(f"Command is on cooldown. Try again in {error.retry_after:.1f}s")
865
elif isinstance(error, commands.MissingPermissions):
866
perms = ', '.join(error.missing_permissions)
867
await ctx.send(f"You're missing permissions: {perms}")
868
elif isinstance(error, commands.BotMissingPermissions):
869
perms = ', '.join(error.missing_permissions)
870
await ctx.send(f"I'm missing permissions: {perms}")
871
elif isinstance(error, commands.CheckFailure):
872
await ctx.send("You don't have permission to use this command.")
873
elif isinstance(error, commands.CommandInvokeError):
874
# Log the original error
875
print(f"Error in {ctx.command}: {error.original}")
876
await ctx.send("An error occurred while executing the command.")
877
878
# Example: Cog-specific Error Handling
879
class MyCog(commands.Cog):
880
async def cog_command_error(self, ctx, error):
881
if isinstance(error, commands.MissingRole):
882
await ctx.send(f"You need the {error.missing_role} role!")
883
else:
884
# Let the global error handler deal with it
885
raise error
886
887
# Example: Extension Loading Error Handling
888
try:
889
bot.load_extension('my_extension')
890
except commands.ExtensionNotFound:
891
print("Extension file not found")
892
except commands.ExtensionAlreadyLoaded:
893
print("Extension already loaded")
894
except commands.NoEntryPointError:
895
print("Extension missing setup function")
896
except commands.ExtensionFailed as e:
897
print(f"Extension failed to load: {e.original}")
898
899
# Example: HTTP Error Handling with Retry Logic
900
import asyncio
901
902
async def safe_api_call(coro, max_retries=3):
903
"""Safely execute an API call with retry logic."""
904
for attempt in range(max_retries):
905
try:
906
return await coro
907
except discord.HTTPException as e:
908
if e.status == 429: # Rate limited
909
# Discord sends retry-after header
910
retry_after = int(e.response.headers.get('Retry-After', 1))
911
await asyncio.sleep(retry_after)
912
continue
913
elif 500 <= e.status < 600: # Server error
914
if attempt < max_retries - 1:
915
await asyncio.sleep(2 ** attempt) # Exponential backoff
916
continue
917
raise # Re-raise if not retryable or max retries exceeded
918
919
raise discord.HTTPException(None, "Max retries exceeded")
920
```
921
922
The error handling system provides comprehensive exception coverage for all aspects of Discord bot development, enabling robust error recovery, informative error messages, and proper debugging capabilities for production Discord applications.