0
# Exception Handling
1
2
Comprehensive exception hierarchy for handling Discord integration errors. Pypresence provides specific exceptions for different failure scenarios, enabling precise error handling and debugging.
3
4
## Capabilities
5
6
### Base Exception
7
8
```python { .api }
9
class PyPresenceException(Exception):
10
def __init__(self, message: str = None):
11
"""
12
Base exception for all pypresence errors.
13
14
Parameters:
15
- message (str): Optional custom error message
16
"""
17
```
18
19
### Connection Exceptions
20
21
```python { .api }
22
class DiscordNotFound(PyPresenceException):
23
def __init__(self):
24
"""
25
Raised when Discord is not installed or not running.
26
27
This exception indicates that the Discord client could not be found
28
on the system or is not currently running.
29
"""
30
```
31
32
```python { .api }
33
class InvalidPipe(PyPresenceException):
34
def __init__(self):
35
"""
36
Raised when the Discord IPC pipe cannot be found.
37
38
This typically occurs when Discord is not running or the IPC
39
communication channels are not available.
40
"""
41
```
42
43
```python { .api }
44
class ConnectionTimeout(PyPresenceException):
45
def __init__(self):
46
"""
47
Raised when unable to create a connection to the pipe in time.
48
49
This occurs when the connection attempt exceeds the specified
50
connection_timeout value.
51
"""
52
```
53
54
```python { .api }
55
class PipeClosed(PyPresenceException):
56
def __init__(self):
57
"""
58
Raised when the Discord IPC pipe is closed unexpectedly.
59
60
This can occur when Discord is closed while maintaining an active
61
connection. Applications should catch this and attempt to reconnect.
62
"""
63
```
64
65
### Communication Exceptions
66
67
```python { .api }
68
class ResponseTimeout(PyPresenceException):
69
def __init__(self):
70
"""
71
Raised when no response is received from Discord RPC in time.
72
73
This occurs when Discord doesn't respond within the specified
74
response_timeout value.
75
"""
76
```
77
78
```python { .api }
79
class ServerError(PyPresenceException):
80
def __init__(self, message: str):
81
"""
82
Raised when Discord server returns an error.
83
84
Parameters:
85
- message (str): Error message from Discord server
86
"""
87
```
88
89
### Discord API Exceptions
90
91
```python { .api }
92
class DiscordError(PyPresenceException):
93
def __init__(self, code: int, message: str, override: bool = False):
94
"""
95
Raised when Discord API returns an error response.
96
97
Parameters:
98
- code (int): Discord error code
99
- message (str): Error message from Discord
100
- override (bool): Whether to use message as-is
101
102
Attributes:
103
- code (int): Discord error code
104
- message (str): Original error message
105
"""
106
```
107
108
```python { .api }
109
class InvalidID(DiscordError):
110
def __init__(self):
111
"""
112
Raised when the Discord application client ID is invalid.
113
114
This occurs when the provided client_id doesn't match any
115
registered Discord application.
116
"""
117
```
118
119
### Parameter Validation Exceptions
120
121
```python { .api }
122
class InvalidArgument(PyPresenceException):
123
def __init__(self, expected, received, description: str = None):
124
"""
125
Raised when invalid arguments are passed to functions.
126
127
Parameters:
128
- expected: Expected argument type or value
129
- received: Actual argument type or value received
130
- description (str): Optional additional description
131
"""
132
```
133
134
```python { .api }
135
class ArgumentError(PyPresenceException):
136
def __init__(self):
137
"""
138
Raised when function arguments are incorrect.
139
140
Typically occurs when event handler functions don't have
141
the correct number of parameters.
142
"""
143
```
144
145
### Event Management Exceptions
146
147
```python { .api }
148
class EventNotFound(PyPresenceException):
149
def __init__(self, event: str):
150
"""
151
Raised when trying to unregister a non-existent event.
152
153
Parameters:
154
- event (str): Name of the event that wasn't found
155
"""
156
```
157
158
## Exception Hierarchy
159
160
```
161
PyPresenceException (base)
162
├── DiscordNotFound
163
├── InvalidPipe
164
├── ConnectionTimeout
165
├── PipeClosed
166
├── ResponseTimeout
167
├── ServerError
168
├── InvalidArgument
169
├── ArgumentError
170
├── EventNotFound
171
└── DiscordError
172
└── InvalidID
173
```
174
175
## Usage Examples
176
177
### Basic Error Handling
178
179
```python
180
from pypresence import Presence
181
from pypresence import (
182
DiscordNotFound, InvalidPipe, PipeClosed,
183
ResponseTimeout, InvalidID
184
)
185
186
def connect_with_retry(client_id, max_retries=3):
187
for attempt in range(max_retries):
188
try:
189
RPC = Presence(client_id)
190
RPC.connect()
191
return RPC
192
except DiscordNotFound:
193
print("Discord is not running. Please start Discord.")
194
return None
195
except InvalidID:
196
print("Invalid client ID. Check your Discord application settings.")
197
return None
198
except (InvalidPipe, ConnectionTimeout) as e:
199
print(f"Connection failed (attempt {attempt + 1}): {e}")
200
if attempt == max_retries - 1:
201
print("Max retries reached. Unable to connect.")
202
return None
203
time.sleep(2) # Wait before retry
204
205
return None
206
```
207
208
### Comprehensive Error Handling
209
210
```python
211
from pypresence import Presence, PyPresenceException
212
import time
213
import logging
214
215
def robust_presence_client(client_id):
216
RPC = None
217
218
try:
219
# Initialize client
220
RPC = Presence(client_id, connection_timeout=10, response_timeout=5)
221
RPC.connect()
222
223
while True:
224
try:
225
# Update presence
226
RPC.update(
227
state="Online",
228
details="Available for chat",
229
large_image="status_online"
230
)
231
time.sleep(15)
232
233
except PipeClosed:
234
logging.warning("Discord connection lost. Attempting to reconnect...")
235
try:
236
RPC.connect()
237
logging.info("Reconnected successfully.")
238
except PyPresenceException as e:
239
logging.error(f"Reconnection failed: {e}")
240
break
241
242
except ResponseTimeout:
243
logging.warning("Discord not responding. Continuing...")
244
continue
245
246
except Exception as e:
247
logging.error(f"Unexpected error: {e}")
248
break
249
250
except DiscordNotFound:
251
logging.error("Discord is not running. Please start Discord and try again.")
252
except InvalidID:
253
logging.error("Invalid client ID. Check your Discord application configuration.")
254
except ConnectionTimeout:
255
logging.error("Connection timeout. Discord may be unresponsive.")
256
except PyPresenceException as e:
257
logging.error(f"PyPresence error: {e}")
258
except Exception as e:
259
logging.error(f"Unexpected error: {e}")
260
finally:
261
if RPC:
262
try:
263
RPC.close()
264
except:
265
pass # Ignore errors during cleanup
266
267
# Usage
268
robust_presence_client("your_client_id")
269
```
270
271
### Event Handler Error Handling
272
273
```python
274
from pypresence import Client, ArgumentError, EventNotFound
275
276
def safe_event_handler(data):
277
"""Event handler that won't crash the application."""
278
try:
279
print(f"Received event data: {data}")
280
# Process event data here
281
except Exception as e:
282
print(f"Error in event handler: {e}")
283
284
def setup_events(client):
285
try:
286
# Register event with proper signature
287
client.register_event("ACTIVITY_JOIN", safe_event_handler)
288
289
# This would raise ArgumentError - wrong number of parameters
290
# client.register_event("ACTIVITY_JOIN", lambda: print("Invalid"))
291
292
except ArgumentError:
293
print("Event handler must accept exactly one parameter.")
294
except Exception as e:
295
print(f"Failed to register event: {e}")
296
297
def cleanup_events(client):
298
try:
299
client.unregister_event("ACTIVITY_JOIN")
300
except EventNotFound:
301
print("Event was not registered.")
302
except Exception as e:
303
print(f"Error unregistering event: {e}")
304
```
305
306
### Async Error Handling
307
308
```python
309
import asyncio
310
from pypresence import AioPresence, PyPresenceException
311
312
async def async_presence_with_error_handling(client_id):
313
RPC = None
314
315
try:
316
RPC = AioPresence(client_id)
317
await RPC.connect()
318
319
# Set initial presence
320
await RPC.update(
321
state="Starting up",
322
details="Initializing application"
323
)
324
325
# Simulate long-running application
326
for i in range(100):
327
try:
328
await RPC.update(
329
state=f"Running - Step {i+1}",
330
details="Processing data"
331
)
332
await asyncio.sleep(10)
333
334
except PyPresenceException as e:
335
print(f"Presence update failed: {e}")
336
# Continue running even if presence update fails
337
continue
338
339
except PyPresenceException as e:
340
print(f"Failed to initialize Discord presence: {e}")
341
finally:
342
if RPC:
343
RPC.close()
344
345
# Run with error handling
346
asyncio.run(async_presence_with_error_handling("your_client_id"))
347
```
348
349
### Custom Error Handling
350
351
```python
352
from pypresence import Presence, PyPresenceException
353
354
class PresenceManager:
355
def __init__(self, client_id, auto_retry=True):
356
self.client_id = client_id
357
self.auto_retry = auto_retry
358
self.RPC = None
359
self._connected = False
360
361
def connect(self):
362
"""Connect with custom error handling."""
363
try:
364
self.RPC = Presence(self.client_id)
365
self.RPC.connect()
366
self._connected = True
367
return True
368
except PyPresenceException as e:
369
self._handle_error(e)
370
return False
371
372
def update_safe(self, **kwargs):
373
"""Update presence with automatic error recovery."""
374
if not self._connected and self.auto_retry:
375
if not self.connect():
376
return False
377
378
try:
379
self.RPC.update(**kwargs)
380
return True
381
except PyPresenceException as e:
382
self._handle_error(e)
383
if self.auto_retry and isinstance(e, (PipeClosed, ResponseTimeout)):
384
self._connected = False
385
return self.update_safe(**kwargs) # Retry once
386
return False
387
388
def _handle_error(self, error):
389
"""Custom error handling logic."""
390
error_actions = {
391
DiscordNotFound: "Please start Discord and try again.",
392
InvalidID: "Check your Discord application client ID.",
393
PipeClosed: "Discord connection lost. Will attempt to reconnect.",
394
ResponseTimeout: "Discord is not responding. Retrying...",
395
}
396
397
action = error_actions.get(type(error), f"Unknown error: {error}")
398
print(f"Discord error: {action}")
399
400
def close(self):
401
"""Clean shutdown."""
402
if self.RPC:
403
self.RPC.close()
404
self._connected = False
405
406
# Usage
407
manager = PresenceManager("your_client_id", auto_retry=True)
408
if manager.connect():
409
manager.update_safe(state="Connected", details="Ready to go!")
410
```