0
# Error Handling
1
2
Comprehensive exception hierarchy providing detailed error information for both ClickHouse-specific operations and standard database errors. The driver includes both native ClickHouse exceptions with server error codes and DB API 2.0 compliant exceptions for standards-based error handling.
3
4
## Capabilities
5
6
### Core ClickHouse Exceptions
7
8
Native exceptions specific to ClickHouse operations with detailed error codes and nested exception support.
9
10
```python { .api }
11
class Error(Exception):
12
"""Base exception class for all ClickHouse driver errors."""
13
14
class ServerException(Error):
15
"""
16
Server-side errors with ClickHouse error codes.
17
18
Attributes:
19
- code: ClickHouse error code (integer)
20
- message: Error message from server
21
- nested: Nested exception if applicable
22
"""
23
24
def __init__(self, message, code=None, nested=None):
25
super().__init__(message)
26
self.code = code
27
self.nested = nested
28
29
class LogicalError(Error):
30
"""Logic errors in query construction or execution."""
31
32
class UnknownTypeError(Error):
33
"""Unknown or unsupported ClickHouse data type."""
34
35
class ChecksumDoesntMatchError(Error):
36
"""Data integrity error during transmission."""
37
38
class TypeMismatchError(Error):
39
"""Type conversion or casting errors."""
40
41
class UnknownCompressionMethod(Error):
42
"""Unsupported compression algorithm."""
43
44
class TooLargeStringSize(Error):
45
"""String size exceeds maximum allowed length."""
46
```
47
48
### Network and Connection Exceptions
49
50
Errors related to network connectivity and connection management.
51
52
```python { .api }
53
class NetworkError(Error):
54
"""Network connectivity errors."""
55
56
class SocketTimeoutError(NetworkError):
57
"""Socket operation timeout."""
58
59
class UnexpectedPacketFromServerError(Error):
60
"""Protocol violation or unexpected server response."""
61
62
class UnknownPacketFromServerError(UnexpectedPacketFromServerError):
63
"""Unknown packet type received from server."""
64
```
65
66
### Data Processing Exceptions
67
68
Errors during data parsing, conversion, and processing operations.
69
70
```python { .api }
71
class CannotParseUuidError(Error):
72
"""UUID parsing or format errors."""
73
74
class CannotParseDomainError(Error):
75
"""Domain name parsing errors."""
76
77
class PartiallyConsumedQueryError(Error):
78
"""
79
Query result not fully consumed.
80
81
Raised when attempting new operations while previous
82
query results are still being processed.
83
"""
84
```
85
86
### Error Code Constants
87
88
ClickHouse server error codes for programmatic error handling.
89
90
```python { .api }
91
class ErrorCodes:
92
"""
93
ClickHouse server error code constants.
94
95
Common error codes:
96
- SYNTAX_ERROR = 62
97
- UNKNOWN_TABLE = 60
98
- UNKNOWN_COLUMN = 47
99
- MEMORY_LIMIT_EXCEEDED = 241
100
- TIMEOUT_BEFORE_PROCESSING_CONNECTION = 159
101
- AUTHENTICATION_FAILED = 516
102
- DATABASE_ACCESS_DENIED = 271
103
- TABLE_ALREADY_EXISTS = 57
104
- COLUMN_ALREADY_EXISTS = 44
105
"""
106
107
# Network and connection errors
108
NETWORK_ERROR = 210
109
SOCKET_TIMEOUT = 209
110
CONNECTION_LOST = 210
111
112
# Authentication and authorization
113
AUTHENTICATION_FAILED = 516
114
DATABASE_ACCESS_DENIED = 271
115
READONLY = 164
116
117
# Query syntax and logic errors
118
SYNTAX_ERROR = 62
119
LOGICAL_ERROR = 170
120
BAD_ARGUMENTS = 36
121
122
# Schema and metadata errors
123
UNKNOWN_DATABASE = 81
124
UNKNOWN_TABLE = 60
125
UNKNOWN_COLUMN = 47
126
TABLE_ALREADY_EXISTS = 57
127
COLUMN_ALREADY_EXISTS = 44
128
129
# Resource limits
130
MEMORY_LIMIT_EXCEEDED = 241
131
TIMEOUT_EXCEEDED = 159
132
QUERY_WAS_CANCELLED = 394
133
134
# Data type and conversion errors
135
TYPE_MISMATCH = 53
136
CANNOT_CONVERT_TYPE = 70
137
CANNOT_PARSE_NUMBER = 27
138
CANNOT_PARSE_DATE = 38
139
```
140
141
### DB API 2.0 Exceptions
142
143
Standard database exceptions following Python DB API 2.0 specification for compatibility with database frameworks.
144
145
```python { .api }
146
# Exception hierarchy following DB API 2.0
147
class Warning(Exception):
148
"""Warning category for non-fatal issues."""
149
150
class Error(Exception):
151
"""Base class for all database-related errors."""
152
153
class InterfaceError(Error):
154
"""
155
Database interface errors.
156
157
Raised for problems with the database interface rather
158
than the database itself.
159
"""
160
161
class DatabaseError(Error):
162
"""
163
Database-related errors.
164
165
Base class for errors related to the database operation.
166
"""
167
168
class DataError(DatabaseError):
169
"""
170
Data processing errors.
171
172
Problems with the processed data like division by zero,
173
numeric value out of range, etc.
174
"""
175
176
class OperationalError(DatabaseError):
177
"""
178
Operational database errors.
179
180
Errors related to database operation, not under user control.
181
Examples: connection lost, database name not found, etc.
182
"""
183
184
class IntegrityError(DatabaseError):
185
"""
186
Database integrity constraint violations.
187
188
Relational integrity of the database is affected.
189
"""
190
191
class InternalError(DatabaseError):
192
"""
193
Internal database errors.
194
195
Database system internal errors.
196
"""
197
198
class ProgrammingError(DatabaseError):
199
"""
200
Programming errors.
201
202
SQL syntax errors, table not found, wrong parameter count, etc.
203
"""
204
205
class NotSupportedError(DatabaseError):
206
"""
207
Unsupported database operations.
208
209
Method or database API not supported by the database.
210
"""
211
```
212
213
## Error Handling Patterns
214
215
### Basic Exception Handling
216
217
```python
218
from clickhouse_driver import Client
219
from clickhouse_driver.errors import Error, ServerException, NetworkError
220
221
client = Client('localhost')
222
223
try:
224
result = client.execute('SELECT invalid_function()')
225
except ServerException as e:
226
print(f"ClickHouse server error: {e}")
227
print(f"Error code: {e.code}")
228
if e.nested:
229
print(f"Nested error: {e.nested}")
230
except NetworkError as e:
231
print(f"Network error: {e}")
232
except Error as e:
233
print(f"General ClickHouse error: {e}")
234
```
235
236
### Server Error Code Handling
237
238
```python
239
from clickhouse_driver import Client
240
from clickhouse_driver.errors import ServerException, ErrorCodes
241
242
client = Client('localhost')
243
244
try:
245
client.execute('SELECT * FROM nonexistent_table')
246
except ServerException as e:
247
if e.code == ErrorCodes.UNKNOWN_TABLE:
248
print("Table doesn't exist - creating it...")
249
client.execute('''
250
CREATE TABLE nonexistent_table (
251
id UInt32,
252
name String
253
) ENGINE = Memory
254
''')
255
elif e.code == ErrorCodes.DATABASE_ACCESS_DENIED:
256
print("Access denied - check permissions")
257
elif e.code == ErrorCodes.SYNTAX_ERROR:
258
print(f"SQL syntax error: {e}")
259
else:
260
print(f"Other server error {e.code}: {e}")
261
```
262
263
### DB API 2.0 Exception Handling
264
265
```python
266
from clickhouse_driver import connect
267
from clickhouse_driver.dbapi.errors import (
268
DatabaseError, OperationalError, ProgrammingError,
269
DataError, IntegrityError
270
)
271
272
try:
273
with connect(host='localhost') as conn:
274
with conn.cursor() as cursor:
275
cursor.execute('SELECT * FROM invalid_table')
276
277
except ProgrammingError as e:
278
print(f"SQL programming error: {e}")
279
except OperationalError as e:
280
print(f"Database operational error: {e}")
281
except DataError as e:
282
print(f"Data processing error: {e}")
283
except IntegrityError as e:
284
print(f"Data integrity error: {e}")
285
except DatabaseError as e:
286
print(f"General database error: {e}")
287
```
288
289
### Connection Error Handling
290
291
```python
292
from clickhouse_driver import Client
293
from clickhouse_driver.errors import NetworkError, SocketTimeoutError
294
295
# Robust connection with retry logic
296
def connect_with_retry(max_retries=3):
297
for attempt in range(max_retries):
298
try:
299
client = Client(
300
'localhost',
301
connect_timeout=5,
302
send_receive_timeout=30
303
)
304
# Test connection
305
client.execute('SELECT 1')
306
return client
307
308
except SocketTimeoutError:
309
print(f"Connection timeout, attempt {attempt + 1}")
310
if attempt == max_retries - 1:
311
raise
312
except NetworkError as e:
313
print(f"Network error: {e}, attempt {attempt + 1}")
314
if attempt == max_retries - 1:
315
raise
316
317
time.sleep(2 ** attempt) # Exponential backoff
318
319
client = connect_with_retry()
320
```
321
322
### Type Error Handling
323
324
```python
325
from clickhouse_driver import Client
326
from clickhouse_driver.errors import TypeMismatchError, UnknownTypeError
327
328
client = Client('localhost')
329
330
try:
331
# Enable strict type checking
332
result = client.execute(
333
'SELECT * FROM test_table WHERE id = %(id)s',
334
{'id': 'invalid_integer'}, # String instead of integer
335
types_check=True
336
)
337
except TypeMismatchError as e:
338
print(f"Type mismatch: {e}")
339
# Handle by converting types or fixing query
340
341
try:
342
# Query with unknown type in result
343
result = client.execute('SELECT some_new_clickhouse_type FROM test')
344
except UnknownTypeError as e:
345
print(f"Unknown ClickHouse type: {e}")
346
# May need driver update or custom type handling
347
```
348
349
### Memory and Resource Error Handling
350
351
```python
352
from clickhouse_driver import Client
353
from clickhouse_driver.errors import ServerException, ErrorCodes
354
355
client = Client('localhost')
356
357
try:
358
# Large query that might exceed memory limits
359
result = client.execute('''
360
SELECT huge_column, COUNT(*)
361
FROM massive_table
362
GROUP BY huge_column
363
''', settings={
364
'max_memory_usage': 1000000000, # 1GB limit
365
'max_execution_time': 300 # 5 minute timeout
366
})
367
368
except ServerException as e:
369
if e.code == ErrorCodes.MEMORY_LIMIT_EXCEEDED:
370
print("Query exceeded memory limit")
371
# Use streaming or reduce data scope
372
for block in client.execute_iter(
373
'SELECT huge_column FROM massive_table LIMIT 1000000'
374
):
375
process_block(block)
376
377
elif e.code == ErrorCodes.TIMEOUT_EXCEEDED:
378
print("Query timed out")
379
# Optimize query or increase timeout
380
381
elif e.code == ErrorCodes.QUERY_WAS_CANCELLED:
382
print("Query was cancelled")
383
# Handle cancellation gracefully
384
```
385
386
### Comprehensive Error Logging
387
388
```python
389
import logging
390
from clickhouse_driver import Client
391
from clickhouse_driver.errors import Error, ServerException
392
393
# Configure logging
394
logging.basicConfig(level=logging.INFO)
395
logger = logging.getLogger(__name__)
396
397
def execute_with_logging(client, query, params=None):
398
try:
399
logger.info(f"Executing query: {query[:100]}...")
400
result = client.execute(query, params)
401
logger.info(f"Query completed successfully, {len(result)} rows")
402
return result
403
404
except ServerException as e:
405
logger.error(f"ClickHouse server error {e.code}: {e}")
406
if e.nested:
407
logger.error(f"Nested error: {e.nested}")
408
raise
409
410
except Error as e:
411
logger.error(f"ClickHouse driver error: {e}")
412
raise
413
414
except Exception as e:
415
logger.error(f"Unexpected error: {e}")
416
raise
417
418
# Usage
419
client = Client('localhost')
420
try:
421
result = execute_with_logging(
422
client,
423
'SELECT count() FROM large_table WHERE date > %(date)s',
424
{'date': '2023-01-01'}
425
)
426
except Error:
427
# Error already logged
428
pass
429
```
430
431
### Graceful Degradation
432
433
```python
434
from clickhouse_driver import Client
435
from clickhouse_driver.errors import ServerException, ErrorCodes
436
437
def query_with_fallback(client, primary_query, fallback_query=None):
438
"""Execute query with fallback on certain errors."""
439
440
try:
441
return client.execute(primary_query)
442
443
except ServerException as e:
444
if e.code in [ErrorCodes.UNKNOWN_TABLE, ErrorCodes.UNKNOWN_COLUMN]:
445
if fallback_query:
446
print(f"Primary query failed, trying fallback: {e}")
447
return client.execute(fallback_query)
448
else:
449
print(f"Schema error, no fallback available: {e}")
450
raise
451
else:
452
# Re-raise other server errors
453
raise
454
455
# Usage with schema evolution
456
client = Client('localhost')
457
458
# Try new schema first, fall back to old schema
459
result = query_with_fallback(
460
client,
461
'SELECT id, name, new_column FROM users', # New schema
462
'SELECT id, name, NULL as new_column FROM users' # Old schema fallback
463
)
464
```