0
# Exception Handling
1
2
Comprehensive exception hierarchy for WebSocket-specific error conditions, connection management, and protocol violations. All exceptions inherit from the base WebSocketException class for consistent error handling patterns.
3
4
## Capabilities
5
6
### Base Exception Class
7
8
Root exception class for all WebSocket-related errors.
9
10
```python { .api }
11
class WebSocketException(Exception):
12
"""
13
Base class for all WebSocket exceptions.
14
15
Provides common interface for WebSocket-specific error handling
16
and allows catching all WebSocket errors with single except clause.
17
"""
18
pass
19
```
20
21
### Protocol Violations
22
23
Exceptions raised when WebSocket protocol rules are violated.
24
25
```python { .api }
26
class WebSocketProtocolException(WebSocketException):
27
"""
28
Raised when WebSocket protocol is violated.
29
30
Indicates frame format errors, invalid opcodes, reserved bit usage,
31
or other protocol-level violations that prevent proper communication.
32
"""
33
pass
34
35
class WebSocketPayloadException(WebSocketException):
36
"""
37
Raised when WebSocket payload is invalid.
38
39
Indicates UTF-8 encoding errors in text frames, invalid close frame
40
payloads, or other data-specific validation failures.
41
"""
42
pass
43
```
44
45
### Connection State Errors
46
47
Exceptions related to WebSocket connection lifecycle and state management.
48
49
```python { .api }
50
class WebSocketConnectionClosedException(WebSocketException):
51
"""
52
Raised when operation attempted on closed connection.
53
54
Indicates the remote host closed the connection, network connection
55
was lost, or operation was attempted after connection closure.
56
"""
57
pass
58
59
class WebSocketTimeoutException(WebSocketException):
60
"""
61
Raised when socket operations exceed timeout limits.
62
63
Occurs during read/write operations, connection establishment,
64
or other time-sensitive WebSocket operations.
65
"""
66
pass
67
```
68
69
### Network and Proxy Errors
70
71
Exceptions related to network connectivity and proxy configuration.
72
73
```python { .api }
74
class WebSocketProxyException(WebSocketException):
75
"""
76
Raised when proxy-related errors occur.
77
78
Indicates proxy connection failures, authentication errors,
79
or proxy configuration problems.
80
"""
81
pass
82
83
class WebSocketAddressException(WebSocketException):
84
"""
85
Raised when WebSocket address cannot be resolved.
86
87
Indicates DNS resolution failures or invalid URL formats
88
that prevent connection establishment.
89
"""
90
pass
91
```
92
93
### HTTP Handshake Errors
94
95
Exception for WebSocket handshake failures with detailed HTTP response information.
96
97
```python { .api }
98
class WebSocketBadStatusException(WebSocketException):
99
"""
100
Raised when WebSocket handshake receives bad HTTP status code.
101
102
Provides access to HTTP response details for debugging
103
handshake failures and server-side errors.
104
"""
105
def __init__(
106
self,
107
message: str,
108
status_code: int,
109
status_message=None,
110
resp_headers=None,
111
resp_body=None,
112
):
113
"""
114
Initialize bad status exception with HTTP response details.
115
116
Parameters:
117
- message: Error description
118
- status_code: HTTP status code from handshake response
119
- status_message: HTTP status message (optional)
120
- resp_headers: HTTP response headers dictionary (optional)
121
- resp_body: HTTP response body content (optional)
122
"""
123
super().__init__(message)
124
self.status_code = status_code
125
self.resp_headers = resp_headers
126
self.resp_body = resp_body
127
```
128
129
## Usage Examples
130
131
### Basic Exception Handling
132
133
```python
134
from websocket import (
135
create_connection,
136
WebSocketException,
137
WebSocketConnectionClosedException,
138
WebSocketTimeoutException
139
)
140
141
try:
142
ws = create_connection("ws://echo.websocket.events/", timeout=5)
143
ws.send("Hello")
144
response = ws.recv()
145
print(f"Received: {response}")
146
ws.close()
147
148
except WebSocketConnectionClosedException:
149
print("Connection was closed unexpectedly")
150
except WebSocketTimeoutException:
151
print("Connection timed out")
152
except WebSocketException as e:
153
print(f"WebSocket error: {e}")
154
except Exception as e:
155
print(f"Unexpected error: {e}")
156
```
157
158
### Handshake Error Analysis
159
160
```python
161
from websocket import create_connection, WebSocketBadStatusException
162
163
try:
164
ws = create_connection("ws://example.com/protected-endpoint")
165
166
except WebSocketBadStatusException as e:
167
print(f"Handshake failed: {e}")
168
print(f"HTTP Status: {e.status_code}")
169
170
if e.resp_headers:
171
print("Response headers:")
172
for header, value in e.resp_headers.items():
173
print(f" {header}: {value}")
174
175
if e.resp_body:
176
print(f"Response body: {e.resp_body}")
177
178
# Handle specific status codes
179
if e.status_code == 401:
180
print("Authentication required")
181
elif e.status_code == 403:
182
print("Access forbidden")
183
elif e.status_code == 404:
184
print("WebSocket endpoint not found")
185
elif e.status_code >= 500:
186
print("Server error occurred")
187
188
except Exception as e:
189
print(f"Other error: {e}")
190
```
191
192
### Protocol Error Handling
193
194
```python
195
from websocket import (
196
WebSocket,
197
WebSocketProtocolException,
198
WebSocketPayloadException,
199
ABNF
200
)
201
202
ws = WebSocket()
203
ws.connect("ws://echo.websocket.events/")
204
205
try:
206
# Attempt to send invalid frame
207
invalid_frame = ABNF(
208
fin=1,
209
rsv1=1, # Invalid - reserved bit set
210
opcode=ABNF.OPCODE_TEXT,
211
data="test"
212
)
213
invalid_frame.validate()
214
215
except WebSocketProtocolException as e:
216
print(f"Protocol violation: {e}")
217
218
try:
219
# Send invalid UTF-8 in text frame
220
invalid_utf8 = b'\xff\xfe' # Invalid UTF-8 sequence
221
ws.send(invalid_utf8.decode('utf-8', errors='ignore'), ABNF.OPCODE_TEXT)
222
223
except WebSocketPayloadException as e:
224
print(f"Payload error: {e}")
225
except UnicodeDecodeError:
226
print("Cannot decode invalid UTF-8")
227
228
ws.close()
229
```
230
231
### Connection State Management
232
233
```python
234
from websocket import WebSocket, WebSocketConnectionClosedException
235
import threading
236
import time
237
238
def message_sender(ws):
239
"""Send messages in background thread."""
240
try:
241
for i in range(10):
242
time.sleep(1)
243
ws.send(f"Message {i}")
244
print(f"Sent message {i}")
245
except WebSocketConnectionClosedException:
246
print("Connection closed while sending")
247
248
def message_receiver(ws):
249
"""Receive messages in background thread."""
250
try:
251
while True:
252
message = ws.recv()
253
print(f"Received: {message}")
254
except WebSocketConnectionClosedException:
255
print("Connection closed while receiving")
256
257
# Create connection
258
ws = WebSocket(enable_multithread=True)
259
ws.connect("ws://echo.websocket.events/")
260
261
# Start background threads
262
sender_thread = threading.Thread(target=message_sender, args=(ws,))
263
receiver_thread = threading.Thread(target=message_receiver, args=(ws,))
264
265
sender_thread.start()
266
receiver_thread.start()
267
268
# Simulate connection interruption after 3 seconds
269
time.sleep(3)
270
ws.close()
271
272
# Wait for threads to handle the closure
273
sender_thread.join()
274
receiver_thread.join()
275
276
print("All threads completed")
277
```
278
279
### Timeout Configuration and Handling
280
281
```python
282
from websocket import create_connection, WebSocketTimeoutException
283
import time
284
285
# Test different timeout scenarios
286
timeout_configs = [
287
{"name": "Fast timeout", "timeout": 1},
288
{"name": "Medium timeout", "timeout": 5},
289
{"name": "No timeout", "timeout": None}
290
]
291
292
for config in timeout_configs:
293
print(f"\nTesting {config['name']} (timeout={config['timeout']})")
294
295
try:
296
ws = create_connection(
297
"ws://echo.websocket.events/",
298
timeout=config['timeout']
299
)
300
301
start_time = time.time()
302
ws.send("ping")
303
response = ws.recv()
304
elapsed = time.time() - start_time
305
306
print(f" Success: received '{response}' in {elapsed:.2f}s")
307
ws.close()
308
309
except WebSocketTimeoutException:
310
print(f" Timeout occurred after {config['timeout']}s")
311
except Exception as e:
312
print(f" Unexpected error: {e}")
313
```
314
315
### Proxy Error Handling
316
317
```python
318
from websocket import create_connection, WebSocketProxyException
319
320
proxy_configs = [
321
{
322
"name": "Invalid proxy host",
323
"http_proxy_host": "nonexistent.proxy.com",
324
"http_proxy_port": 8080
325
},
326
{
327
"name": "Wrong proxy port",
328
"http_proxy_host": "proxy.company.com",
329
"http_proxy_port": 9999
330
},
331
{
332
"name": "Authentication required",
333
"http_proxy_host": "authenticated.proxy.com",
334
"http_proxy_port": 8080
335
# Missing http_proxy_auth
336
}
337
]
338
339
for config in proxy_configs:
340
print(f"\nTesting {config['name']}")
341
342
try:
343
ws = create_connection(
344
"ws://echo.websocket.events/",
345
http_proxy_host=config["http_proxy_host"],
346
http_proxy_port=config["http_proxy_port"],
347
http_proxy_auth=config.get("http_proxy_auth")
348
)
349
print(" Proxy connection successful")
350
ws.close()
351
352
except WebSocketProxyException as e:
353
print(f" Proxy error: {e}")
354
except Exception as e:
355
print(f" Other error: {e}")
356
```
357
358
### Comprehensive Error Recovery
359
360
```python
361
from websocket import (
362
WebSocketApp,
363
WebSocketException,
364
WebSocketConnectionClosedException,
365
WebSocketTimeoutException,
366
WebSocketBadStatusException
367
)
368
import time
369
370
class RobustWebSocketClient:
371
def __init__(self, url):
372
self.url = url
373
self.ws = None
374
self.reconnect_attempts = 0
375
self.max_reconnect_attempts = 5
376
377
def connect(self):
378
"""Connect with comprehensive error handling."""
379
while self.reconnect_attempts < self.max_reconnect_attempts:
380
try:
381
print(f"Connection attempt {self.reconnect_attempts + 1}")
382
383
self.ws = WebSocketApp(
384
self.url,
385
on_open=self.on_open,
386
on_message=self.on_message,
387
on_error=self.on_error,
388
on_close=self.on_close
389
)
390
391
self.ws.run_forever(
392
ping_interval=30,
393
ping_timeout=10,
394
reconnect=5
395
)
396
break
397
398
except WebSocketBadStatusException as e:
399
print(f"Handshake failed (HTTP {e.status_code}): {e}")
400
if e.status_code in [401, 403, 404]:
401
print("Permanent error, not retrying")
402
break
403
404
except WebSocketConnectionClosedException:
405
print("Connection closed, will retry")
406
407
except WebSocketTimeoutException:
408
print("Connection timeout, will retry")
409
410
except WebSocketException as e:
411
print(f"WebSocket error: {e}")
412
413
except Exception as e:
414
print(f"Unexpected error: {e}")
415
416
self.reconnect_attempts += 1
417
if self.reconnect_attempts < self.max_reconnect_attempts:
418
wait_time = min(30, 2 ** self.reconnect_attempts)
419
print(f"Waiting {wait_time}s before retry...")
420
time.sleep(wait_time)
421
422
if self.reconnect_attempts >= self.max_reconnect_attempts:
423
print("Max reconnection attempts reached, giving up")
424
425
def on_open(self, ws):
426
print("Connection established")
427
self.reconnect_attempts = 0 # Reset on successful connection
428
429
def on_message(self, ws, message):
430
print(f"Received: {message}")
431
432
def on_error(self, ws, error):
433
print(f"WebSocket error: {error}")
434
435
def on_close(self, ws, close_status_code, close_msg):
436
print(f"Connection closed: {close_status_code} - {close_msg}")
437
438
# Usage
439
client = RobustWebSocketClient("ws://echo.websocket.events/")
440
client.connect()
441
```