0
# Exception Handling
1
2
Comprehensive exception hierarchy for handling various error conditions including HTTP errors, connection issues, authentication failures, and serialization problems. The client provides specific exception types for different error scenarios to enable proper error handling.
3
4
## Exception Hierarchy
5
6
### Base Exceptions
7
8
```python { .api }
9
class ApiError(Exception):
10
"""
11
Base class for all API-related errors.
12
13
Attributes:
14
- message: Error message
15
- meta: API response metadata
16
- body: Response body containing error details
17
"""
18
def __init__(self, message, meta=None, body=None): ...
19
@property
20
def status_code(self) -> int: ...
21
@property
22
def error(self) -> str: ...
23
@property
24
def info(self) -> Dict[str, Any]: ...
25
26
class TransportError(Exception):
27
"""
28
Transport layer errors from elastic-transport library.
29
30
Attributes:
31
- message: Error description
32
- errors: List of underlying errors
33
"""
34
def __init__(self, message, errors=None): ...
35
36
class SerializationError(Exception):
37
"""
38
Errors during JSON serialization/deserialization.
39
40
Attributes:
41
- message: Error description
42
- original_exception: Underlying serialization error
43
"""
44
def __init__(self, message, original_exception=None): ...
45
46
class ConnectionError(TransportError):
47
"""
48
Connection-related errors including network issues.
49
50
Attributes:
51
- message: Error description
52
- errors: Connection error details
53
"""
54
55
class SSLError(ConnectionError):
56
"""
57
SSL/TLS certificate and connection errors.
58
59
Attributes:
60
- message: SSL error description
61
- errors: SSL error details
62
"""
63
64
class ConnectionTimeout(ConnectionError):
65
"""
66
Connection timeout errors.
67
68
Attributes:
69
- message: Timeout error description
70
- timeout: Timeout value that was exceeded
71
"""
72
```
73
74
### HTTP Status Code Exceptions
75
76
```python { .api }
77
class BadRequestError(ApiError):
78
"""
79
HTTP 400 Bad Request errors.
80
81
Raised when:
82
- Invalid query syntax
83
- Missing required parameters
84
- Invalid parameter values
85
- Malformed request body
86
"""
87
88
class AuthenticationException(ApiError):
89
"""
90
HTTP 401 Unauthorized errors.
91
92
Raised when:
93
- Invalid credentials
94
- Missing authentication
95
- Expired tokens
96
- Invalid API keys
97
"""
98
99
class AuthorizationException(ApiError):
100
"""
101
HTTP 403 Forbidden errors.
102
103
Raised when:
104
- Insufficient privileges
105
- Access to restricted resources
106
- Security policy violations
107
"""
108
109
class NotFoundError(ApiError):
110
"""
111
HTTP 404 Not Found errors.
112
113
Raised when:
114
- Index does not exist
115
- Document not found
116
- Template not found
117
- Alias not found
118
"""
119
120
class ConflictError(ApiError):
121
"""
122
HTTP 409 Conflict errors.
123
124
Raised when:
125
- Version conflicts during updates
126
- Resource already exists
127
- Concurrent modification conflicts
128
- Index already exists
129
"""
130
131
class UnsupportedProductError(ApiError):
132
"""
133
Error when connecting to unsupported Elasticsearch products.
134
135
Raised when:
136
- Connecting to incompatible server
137
- Server doesn't identify as Elasticsearch
138
- Unsupported server version
139
"""
140
```
141
142
### Warning Types
143
144
```python { .api }
145
class ElasticsearchWarning(UserWarning):
146
"""
147
Deprecation and usage warnings from Elasticsearch.
148
149
Attributes:
150
- message: Warning message
151
- category: Warning category
152
"""
153
154
# Legacy alias
155
ElasticsearchDeprecationWarning = ElasticsearchWarning
156
```
157
158
### Legacy Exception Aliases
159
160
```python { .api }
161
# Legacy aliases for backward compatibility
162
RequestError = BadRequestError
163
```
164
165
## Error Response Structure
166
167
```python { .api }
168
class ErrorInfo:
169
"""
170
Elasticsearch error information structure.
171
172
Attributes:
173
- type: Error type (e.g., 'index_not_found_exception')
174
- reason: Human-readable error description
175
- index: Index name (if applicable)
176
- shard: Shard information (if applicable)
177
- caused_by: Nested error information
178
- root_cause: Root cause of the error
179
- stack_trace: Server-side stack trace (if available)
180
"""
181
def __init__(self, error_dict: Dict[str, Any]): ...
182
@property
183
def type(self) -> str: ...
184
@property
185
def reason(self) -> str: ...
186
@property
187
def index(self) -> Optional[str]: ...
188
```
189
190
## Usage Examples
191
192
### Basic Exception Handling
193
194
```python
195
from elasticsearch import Elasticsearch, NotFoundError, ConflictError, ApiError
196
197
client = Elasticsearch(hosts=['http://localhost:9200'])
198
199
try:
200
# Attempt to get a document
201
response = client.get(index="products", id="123")
202
print(response.body['_source'])
203
204
except NotFoundError as e:
205
print(f"Document not found: {e.message}")
206
print(f"Index: {e.info.get('index')}")
207
print(f"ID: {e.info.get('id')}")
208
209
except ApiError as e:
210
print(f"API error: {e.message}")
211
print(f"Status code: {e.status_code}")
212
print(f"Error type: {e.error}")
213
```
214
215
### Handling Version Conflicts
216
217
```python
218
from elasticsearch import ConflictError
219
220
try:
221
# Update with version control
222
client.update(
223
index="products",
224
id="123",
225
document={"price": 99.99},
226
if_seq_no=10,
227
if_primary_term=1
228
)
229
230
except ConflictError as e:
231
print(f"Version conflict: {e.message}")
232
233
# Get current document version
234
current_doc = client.get(index="products", id="123")
235
current_seq_no = current_doc.body['_seq_no']
236
current_primary_term = current_doc.body['_primary_term']
237
238
# Retry with current version
239
try:
240
client.update(
241
index="products",
242
id="123",
243
document={"price": 99.99},
244
if_seq_no=current_seq_no,
245
if_primary_term=current_primary_term
246
)
247
except ConflictError:
248
print("Still conflicting, manual intervention required")
249
```
250
251
### Connection Error Handling
252
253
```python
254
from elasticsearch import ConnectionError, ConnectionTimeout, SSLError
255
256
try:
257
client = Elasticsearch(
258
hosts=['https://elasticsearch.example.com:9200'],
259
http_auth=('username', 'password'),
260
timeout=30
261
)
262
263
response = client.ping()
264
265
except ConnectionTimeout as e:
266
print(f"Connection timed out: {e.message}")
267
print("Try increasing the timeout or check network connectivity")
268
269
except SSLError as e:
270
print(f"SSL error: {e.message}")
271
print("Check SSL certificate configuration")
272
273
except ConnectionError as e:
274
print(f"Connection failed: {e.message}")
275
print("Check if Elasticsearch is running and accessible")
276
```
277
278
### Bulk Operation Error Handling
279
280
```python
281
from elasticsearch.helpers import BulkIndexError, bulk
282
283
def safe_bulk_index(client, actions):
284
"""Safely perform bulk indexing with error handling."""
285
try:
286
success_count, failed_items = bulk(
287
client,
288
actions,
289
raise_on_error=False,
290
raise_on_exception=False
291
)
292
293
print(f"Successfully indexed: {success_count} documents")
294
295
if failed_items:
296
print(f"Failed to index: {len(failed_items)} documents")
297
for item in failed_items:
298
print(f"Failed item: {item}")
299
300
except BulkIndexError as e:
301
print(f"Bulk indexing failed: {e}")
302
303
# Process individual errors
304
for error in e.errors:
305
action = error.get('index', error.get('create', error.get('update', {})))
306
if 'error' in action:
307
print(f"Error in document {action.get('_id', 'unknown')}: {action['error']['reason']}")
308
309
# Usage
310
actions = [
311
{
312
"_index": "products",
313
"_id": "1",
314
"_source": {"name": "Product 1", "price": 10.99}
315
},
316
{
317
"_index": "products",
318
"_id": "2",
319
"_source": {"name": "Product 2", "price": 20.99}
320
}
321
]
322
323
safe_bulk_index(client, actions)
324
```
325
326
### Authentication Error Handling
327
328
```python
329
from elasticsearch import AuthenticationException, AuthorizationException
330
331
try:
332
client = Elasticsearch(
333
hosts=['http://localhost:9200'],
334
http_auth=('username', 'wrong_password')
335
)
336
337
# Attempt an operation that requires authentication
338
client.cluster.health()
339
340
except AuthenticationException as e:
341
print(f"Authentication failed: {e.message}")
342
print("Check username and password")
343
344
except AuthorizationException as e:
345
print(f"Authorization failed: {e.message}")
346
print("User lacks required privileges")
347
```
348
349
### Comprehensive Error Handling Wrapper
350
351
```python
352
from elasticsearch import (
353
Elasticsearch,
354
ApiError,
355
ConnectionError,
356
NotFoundError,
357
ConflictError,
358
AuthenticationException,
359
SerializationError
360
)
361
import logging
362
363
class ElasticsearchClient:
364
"""Wrapper with comprehensive error handling."""
365
366
def __init__(self, **kwargs):
367
self.client = Elasticsearch(**kwargs)
368
self.logger = logging.getLogger(__name__)
369
370
def safe_get(self, index, doc_id, **kwargs):
371
"""Safely get a document with proper error handling."""
372
try:
373
return self.client.get(index=index, id=doc_id, **kwargs)
374
375
except NotFoundError:
376
self.logger.info(f"Document {doc_id} not found in index {index}")
377
return None
378
379
except ConnectionError as e:
380
self.logger.error(f"Connection error: {e}")
381
raise
382
383
except ApiError as e:
384
self.logger.error(f"API error: {e.message} (status: {e.status_code})")
385
raise
386
387
def safe_index(self, index, doc_id, document, **kwargs):
388
"""Safely index a document with retry logic."""
389
max_retries = 3
390
retry_count = 0
391
392
while retry_count < max_retries:
393
try:
394
return self.client.index(
395
index=index,
396
id=doc_id,
397
document=document,
398
**kwargs
399
)
400
401
except ConflictError as e:
402
if retry_count == max_retries - 1:
403
self.logger.error(f"Version conflict after {max_retries} retries")
404
raise
405
406
self.logger.warning(f"Version conflict, retrying... ({retry_count + 1}/{max_retries})")
407
retry_count += 1
408
409
except SerializationError as e:
410
self.logger.error(f"Serialization error: {e}")
411
raise
412
413
except ApiError as e:
414
self.logger.error(f"API error during indexing: {e.message}")
415
raise
416
417
# Usage
418
client = ElasticsearchClient(hosts=['http://localhost:9200'])
419
420
# Safe operations
421
doc = client.safe_get("products", "123")
422
if doc:
423
print(f"Found document: {doc.body['_source']}")
424
425
client.safe_index(
426
"products",
427
"124",
428
{"name": "New Product", "price": 29.99}
429
)
430
```