docs
0
# Error Handling and Exceptions
1
2
Azure Core provides a comprehensive exception hierarchy designed to handle various error conditions that can occur when interacting with Azure services. The exception system enables consistent error handling across all Azure SDK clients.
3
4
## Core Exception Hierarchy
5
6
All Azure Core exceptions inherit from the base `AzureError` class, providing a consistent interface for error handling.
7
8
```python { .api }
9
from azure.core.exceptions import AzureError
10
11
class AzureError(Exception):
12
"""Base exception for all Azure SDK errors."""
13
def __init__(self, message: str = None, **kwargs): ...
14
15
@property
16
def message(self) -> str: ...
17
18
@property
19
def error(self) -> Optional[object]: ...
20
21
@property
22
def continuation_token(self) -> Optional[str]: ...
23
```
24
25
## Capabilities
26
27
### Service Request and Response Errors
28
29
Errors that occur during HTTP request preparation and response processing.
30
31
```python { .api }
32
from azure.core.exceptions import ServiceRequestError, ServiceResponseError, HttpResponseError
33
34
class ServiceRequestError(AzureError):
35
"""Error occurred during request preparation."""
36
def __init__(self, message: str = None, **kwargs): ...
37
38
class ServiceResponseError(AzureError):
39
"""Error occurred during response processing."""
40
def __init__(self, message: str = None, **kwargs): ...
41
42
class HttpResponseError(AzureError):
43
"""HTTP response error with status code information."""
44
def __init__(self, message: str = None, response: HttpResponse = None, **kwargs): ...
45
46
@property
47
def status_code(self) -> Optional[int]: ...
48
49
@property
50
def response(self) -> Optional[HttpResponse]: ...
51
52
@property
53
def reason(self) -> Optional[str]: ...
54
```
55
56
### HTTP Status Code Specific Errors
57
58
Specialized exceptions for common HTTP status codes and error conditions.
59
60
```python { .api }
61
from azure.core.exceptions import (
62
ResourceExistsError, ResourceNotFoundError, ResourceModifiedError,
63
ResourceNotModifiedError, ClientAuthenticationError
64
)
65
66
class ResourceExistsError(HttpResponseError):
67
"""Resource already exists error (typically 409)."""
68
pass
69
70
class ResourceNotFoundError(HttpResponseError):
71
"""Resource not found error (404/412)."""
72
pass
73
74
class ResourceModifiedError(HttpResponseError):
75
"""Resource was modified error (412 with etag mismatch)."""
76
pass
77
78
class ResourceNotModifiedError(HttpResponseError):
79
"""Resource not modified error (304)."""
80
pass
81
82
class ClientAuthenticationError(HttpResponseError):
83
"""Authentication error (401/403)."""
84
pass
85
```
86
87
### Network and Transport Errors
88
89
Errors related to network connectivity and HTTP transport.
90
91
```python { .api }
92
from azure.core.exceptions import (
93
TooManyRedirectsError, ServiceRequestTimeoutError, ServiceResponseTimeoutError,
94
IncompleteReadError
95
)
96
97
class TooManyRedirectsError(ServiceRequestError):
98
"""Maximum redirect attempts exceeded."""
99
def __init__(self, history: Optional[List] = None, **kwargs): ...
100
101
@property
102
def history(self) -> Optional[List]: ...
103
104
class ServiceRequestTimeoutError(ServiceRequestError):
105
"""Service request timeout error."""
106
pass
107
108
class ServiceResponseTimeoutError(ServiceResponseError):
109
"""Service response timeout error."""
110
pass
111
112
class IncompleteReadError(ServiceResponseError):
113
"""Incomplete read error during response processing."""
114
pass
115
```
116
117
### Stream and Content Errors
118
119
Errors related to request/response stream handling and content processing.
120
121
```python { .api }
122
from azure.core.exceptions import (
123
StreamConsumedError, StreamClosedError, ResponseNotReadError
124
)
125
126
class StreamConsumedError(AzureError):
127
"""Stream has already been consumed and cannot be read again."""
128
pass
129
130
class StreamClosedError(AzureError):
131
"""Stream has been closed and cannot be accessed."""
132
pass
133
134
class ResponseNotReadError(AzureError):
135
"""Response content has not been read yet."""
136
pass
137
```
138
139
### Serialization and Deserialization Errors
140
141
Errors that occur during data serialization and deserialization.
142
143
```python { .api }
144
from azure.core.exceptions import SerializationError, DeserializationError, DecodeError
145
146
class SerializationError(AzureError):
147
"""Error occurred during data serialization."""
148
pass
149
150
class DeserializationError(AzureError):
151
"""Error occurred during data deserialization."""
152
pass
153
154
class DecodeError(ServiceResponseError):
155
"""Response content decoding error."""
156
pass
157
```
158
159
### OData Error Handling
160
161
Support for OData V4 error format parsing commonly used by Azure services.
162
163
```python { .api }
164
from azure.core.exceptions import ODataV4Format, ODataV4Error
165
166
class ODataV4Format:
167
"""OData V4 error format parser."""
168
@staticmethod
169
def deserialize(response: HttpResponse) -> Dict: ...
170
171
class ODataV4Error(HttpResponseError):
172
"""OData V4 formatted error response."""
173
def __init__(self, response: HttpResponse, **kwargs): ...
174
175
@property
176
def code(self) -> Optional[str]: ...
177
178
@property
179
def details(self) -> Optional[List[Dict]]: ...
180
```
181
182
### Exception Mapping Utilities
183
184
Utilities for mapping HTTP status codes to appropriate exception types.
185
186
```python { .api }
187
from azure.core.exceptions import map_error
188
from typing import Dict, Type, Callable
189
190
def map_error(
191
status_code: int,
192
response: HttpResponse,
193
error_map: Optional[Dict[int, Type[HttpResponseError]]] = None
194
) -> None:
195
"""Map HTTP status codes to exception types and raise appropriate error."""
196
...
197
198
# Deprecated utility function
199
def raise_with_traceback(exception: Exception, traceback=None) -> None:
200
"""Raise exception with traceback (deprecated)."""
201
...
202
```
203
204
## Usage Examples
205
206
### Basic Exception Handling
207
208
```python
209
from azure.core.exceptions import AzureError, HttpResponseError, ResourceNotFoundError
210
from azure.core import PipelineClient
211
212
try:
213
client = PipelineClient(base_url="https://api.example.com")
214
# Make request...
215
except ResourceNotFoundError as e:
216
print(f"Resource not found: {e.message}")
217
print(f"Status code: {e.status_code}")
218
except HttpResponseError as e:
219
print(f"HTTP error: {e.status_code} - {e.reason}")
220
except AzureError as e:
221
print(f"Azure error: {e.message}")
222
except Exception as e:
223
print(f"Unexpected error: {e}")
224
```
225
226
### Custom Error Mapping
227
228
```python
229
from azure.core.exceptions import map_error, HttpResponseError
230
231
# Define custom error mapping
232
error_map = {
233
404: ResourceNotFoundError,
234
409: ResourceExistsError,
235
401: ClientAuthenticationError,
236
}
237
238
def handle_response(response):
239
if response.status_code >= 400:
240
# Use custom error mapping
241
map_error(response.status_code, response, error_map)
242
return response
243
```
244
245
### Handling Specific Service Errors
246
247
```python
248
from azure.core.exceptions import HttpResponseError, ODataV4Error
249
import json
250
251
try:
252
# Make service request...
253
pass
254
except HttpResponseError as e:
255
if e.response and e.response.headers.get("content-type", "").startswith("application/json"):
256
try:
257
error_details = e.response.json()
258
if "error" in error_details:
259
# Handle OData error format
260
error_code = error_details["error"].get("code")
261
error_message = error_details["error"].get("message")
262
print(f"Service error {error_code}: {error_message}")
263
else:
264
print(f"Service returned error: {error_details}")
265
except (json.JSONDecodeError, KeyError):
266
print(f"Non-JSON error response: {e.message}")
267
else:
268
print(f"HTTP error {e.status_code}: {e.reason}")
269
```
270
271
### Retry Logic with Exception Handling
272
273
```python
274
from azure.core.exceptions import AzureError, ServiceRequestError
275
import time
276
import random
277
278
def retry_with_backoff(func, max_retries=3, base_delay=1.0):
279
"""Retry function with exponential backoff."""
280
for attempt in range(max_retries + 1):
281
try:
282
return func()
283
except (ServiceRequestError, ConnectionError) as e:
284
if attempt == max_retries:
285
raise e
286
287
delay = base_delay * (2 ** attempt) + random.uniform(0, 1)
288
print(f"Attempt {attempt + 1} failed, retrying in {delay:.2f}s...")
289
time.sleep(delay)
290
except AzureError:
291
# Don't retry on non-transient Azure errors
292
raise
293
294
# Usage
295
def make_request():
296
# Your request logic here
297
pass
298
299
try:
300
result = retry_with_backoff(make_request, max_retries=5)
301
except AzureError as e:
302
print(f"Request failed after all retries: {e}")
303
```
304
305
### Stream Error Handling
306
307
```python
308
from azure.core.exceptions import StreamConsumedError, StreamClosedError
309
310
def read_stream_safely(response):
311
try:
312
# Read stream content
313
content = response.content
314
return content
315
except StreamConsumedError:
316
print("Stream has already been consumed")
317
return None
318
except StreamClosedError:
319
print("Stream has been closed")
320
return None
321
322
def read_stream_multiple_times(response):
323
"""Example of handling stream consumption."""
324
try:
325
# First read
326
content1 = response.text
327
328
# Second read will fail
329
content2 = response.text
330
331
except StreamConsumedError:
332
print("Cannot read stream multiple times without reopening")
333
# Would need to make a new request to get content again
334
```
335
336
### Async Exception Handling
337
338
```python
339
import asyncio
340
from azure.core.exceptions import AzureError, HttpResponseError
341
342
async def async_request_with_error_handling():
343
try:
344
# Make async request...
345
pass
346
except HttpResponseError as e:
347
print(f"Async HTTP error: {e.status_code}")
348
# Handle specific async error conditions
349
if e.status_code == 429: # Rate limited
350
# Wait before retrying
351
await asyncio.sleep(1)
352
except AzureError as e:
353
print(f"Async Azure error: {e.message}")
354
355
# asyncio.run(async_request_with_error_handling())
356
```
357
358
## Error Response Processing
359
360
### OData V4 Error Format
361
362
Many Azure services return errors in OData V4 format:
363
364
```json
365
{
366
"error": {
367
"code": "InvalidResourceName",
368
"message": "The specified resource name contains invalid characters.",
369
"details": [
370
{
371
"code": "InvalidCharacter",
372
"message": "Character '@' is not allowed in resource names.",
373
"target": "resourceName"
374
}
375
]
376
}
377
}
378
```
379
380
```python
381
from azure.core.exceptions import ODataV4Format
382
383
def parse_odata_error(response):
384
if response.headers.get("content-type", "").startswith("application/json"):
385
error_data = ODataV4Format.deserialize(response)
386
if error_data:
387
main_error = error_data.get("error", {})
388
code = main_error.get("code")
389
message = main_error.get("message")
390
details = main_error.get("details", [])
391
392
print(f"Error code: {code}")
393
print(f"Error message: {message}")
394
for detail in details:
395
print(f"Detail: {detail.get('message')} (target: {detail.get('target')})")
396
```
397
398
## Best Practices
399
400
### Exception Handling Strategy
401
402
- Catch specific exceptions before general ones (most specific first)
403
- Always catch `AzureError` as a fallback for Azure SDK specific errors
404
- Log exception details including status codes and response content when available
405
- Don't ignore exceptions - handle them appropriately or let them bubble up
406
407
### Error Information Extraction
408
409
- Use the `response` property of `HttpResponseError` to access full response details
410
- Check response headers and content for additional error information
411
- Parse JSON error responses for structured error details
412
- Consider the `continuation_token` property for resumable operations
413
414
### Retry and Recovery
415
416
- Only retry on transient errors (network issues, rate limiting, temporary service errors)
417
- Don't retry on authentication errors or client-side validation errors
418
- Implement exponential backoff with jitter for retry logic
419
- Set reasonable maximum retry limits to avoid infinite loops
420
421
### Logging and Monitoring
422
423
- Log all exceptions with sufficient context for debugging
424
- Include request IDs when available for correlation with service logs
425
- Monitor error rates and patterns to identify service issues
426
- Use structured logging for better error analysis and alerting