0
# Error Handling
1
2
Comprehensive exception hierarchy for handling various error conditions that can occur during web service requests and database lookups. The exceptions provide detailed information about failures including network errors, authentication problems, and data availability issues.
3
4
```python
5
import ipaddress
6
from typing import Optional, Union
7
```
8
9
## Capabilities
10
11
### Base Exception
12
13
The root exception class for all GeoIP2-specific errors.
14
15
```python { .api }
16
class GeoIP2Error(RuntimeError):
17
"""
18
Base exception for all GeoIP2 errors.
19
20
This class represents a generic error and extends RuntimeError
21
without adding additional attributes.
22
"""
23
```
24
25
### Address Lookup Errors
26
27
Exceptions related to IP address lookup failures.
28
29
```python { .api }
30
class AddressNotFoundError(GeoIP2Error):
31
"""
32
The IP address was not found in the database or web service.
33
34
For database lookups, this provides the network information
35
for efficient subnet enumeration.
36
"""
37
38
def __init__(self, message: str, ip_address: Optional[str] = None,
39
prefix_len: Optional[int] = None): ...
40
41
ip_address: Optional[str] # IP address used in lookup (database only)
42
43
@property
44
def network(self) -> Optional[Union[ipaddress.IPv4Network, ipaddress.IPv6Network]]:
45
"""
46
The network associated with the error.
47
48
For database lookups, this is the largest network where no address
49
would be found. Useful for efficient subnet enumeration.
50
51
Returns:
52
Network object or None if not available
53
"""
54
```
55
56
### Authentication and Authorization Errors
57
58
Exceptions for credential and permission issues with web services.
59
60
```python { .api }
61
class AuthenticationError(GeoIP2Error):
62
"""
63
Authentication failed due to invalid credentials.
64
65
This occurs when the account ID or license key is invalid,
66
missing, or unauthorized for the requested service.
67
"""
68
69
class PermissionRequiredError(GeoIP2Error):
70
"""
71
The account does not have permission to access the requested service.
72
73
This typically occurs when trying to access Insights endpoint
74
without an Insights subscription.
75
"""
76
77
class OutOfQueriesError(GeoIP2Error):
78
"""
79
The account has exceeded its query limit or is out of funds.
80
81
Check your MaxMind account for remaining queries or billing status.
82
"""
83
```
84
85
### Network and Request Errors
86
87
Exceptions for HTTP transport and network communication issues.
88
89
```python { .api }
90
class HTTPError(GeoIP2Error):
91
"""
92
An HTTP transport error occurred during the web service request.
93
94
This represents network-level failures, server errors, or
95
unexpected HTTP responses.
96
"""
97
98
def __init__(self, message: str, http_status: Optional[int] = None,
99
uri: Optional[str] = None, decoded_content: Optional[str] = None): ...
100
101
http_status: Optional[int] # HTTP status code returned
102
uri: Optional[str] # URI that was queried
103
decoded_content: Optional[str] # Response body content
104
105
class InvalidRequestError(GeoIP2Error):
106
"""
107
The request was invalid or malformed.
108
109
This can occur with invalid IP addresses, unsupported parameters,
110
or other client-side request errors.
111
"""
112
```
113
114
## Usage Examples
115
116
### Basic Error Handling
117
118
```python
119
import geoip2.webservice
120
from geoip2.errors import (
121
AddressNotFoundError,
122
AuthenticationError,
123
OutOfQueriesError,
124
HTTPError
125
)
126
127
try:
128
with geoip2.webservice.Client(42, 'license_key') as client:
129
response = client.city('127.0.0.1') # Private IP
130
print(response.country.name)
131
132
except AddressNotFoundError:
133
print("IP address not found in database")
134
135
except AuthenticationError:
136
print("Invalid account ID or license key")
137
138
except OutOfQueriesError:
139
print("Account is out of queries")
140
141
except HTTPError as e:
142
print(f"HTTP error {e.http_status}: {e.decoded_content}")
143
144
except GeoIP2Error as e:
145
print(f"Other GeoIP2 error: {e}")
146
```
147
148
### Database Error Handling with Network Information
149
150
```python
151
import geoip2.database
152
from geoip2.errors import AddressNotFoundError
153
154
try:
155
with geoip2.database.Reader('/path/to/GeoLite2-City.mmdb') as reader:
156
response = reader.city('10.0.0.1') # Private IP
157
158
except AddressNotFoundError as e:
159
print(f"Address {e.ip_address} not found")
160
if e.network:
161
print(f"No data available for entire network: {e.network}")
162
163
except FileNotFoundError:
164
print("Database file not found")
165
166
except PermissionError:
167
print("Permission denied accessing database file")
168
```
169
170
### Comprehensive Web Service Error Handling
171
172
```python
173
import geoip2.webservice
174
from geoip2.errors import (
175
AddressNotFoundError,
176
AuthenticationError,
177
PermissionRequiredError,
178
OutOfQueriesError,
179
InvalidRequestError,
180
HTTPError,
181
GeoIP2Error
182
)
183
184
def lookup_ip_with_error_handling(ip_address):
185
try:
186
with geoip2.webservice.Client(42, 'license_key') as client:
187
# Try Insights first (most comprehensive data)
188
try:
189
return client.insights(ip_address)
190
except PermissionRequiredError:
191
# Fall back to City if no Insights permission
192
return client.city(ip_address)
193
194
except AddressNotFoundError:
195
print(f"IP {ip_address} not found in database")
196
return None
197
198
except AuthenticationError:
199
print("Authentication failed - check account ID and license key")
200
return None
201
202
except OutOfQueriesError:
203
print("Account out of queries - check billing status")
204
return None
205
206
except InvalidRequestError as e:
207
print(f"Invalid request: {e}")
208
return None
209
210
except HTTPError as e:
211
if e.http_status == 500:
212
print("Server error - try again later")
213
elif e.http_status == 503:
214
print("Service unavailable - try again later")
215
else:
216
print(f"HTTP error {e.http_status}: {e.decoded_content}")
217
return None
218
219
except GeoIP2Error as e:
220
print(f"Unexpected GeoIP2 error: {e}")
221
return None
222
```
223
224
### Efficient Subnet Enumeration Using Error Networks
225
226
```python
227
import geoip2.database
228
import geoip2.errors
229
import ipaddress
230
231
def enumerate_subnet_with_error_handling(database_path, subnet):
232
"""
233
Efficiently enumerate a subnet using AddressNotFoundError.network
234
to skip entire ranges with no data.
235
"""
236
try:
237
with geoip2.database.Reader(database_path) as reader:
238
network = ipaddress.ip_network(subnet)
239
ip_address = network[0]
240
241
while ip_address in network:
242
try:
243
response = reader.asn(ip_address)
244
response_network = response.network
245
print(f"{response_network}: ASN {response.autonomous_system_number}")
246
247
except geoip2.errors.AddressNotFoundError as e:
248
response_network = e.network
249
if response_network:
250
print(f"{response_network}: No data")
251
else:
252
# Single IP with no data
253
response_network = ipaddress.ip_network(f"{ip_address}/32", strict=False)
254
print(f"{ip_address}: No data")
255
256
# Move to next subnet
257
ip_address = response_network[-1] + 1
258
259
except FileNotFoundError:
260
print(f"Database file not found: {database_path}")
261
except PermissionError:
262
print(f"Permission denied: {database_path}")
263
except Exception as e:
264
print(f"Unexpected error: {e}")
265
```
266
267
### Retry Logic for Transient Errors
268
269
```python
270
import time
271
import geoip2.webservice
272
from geoip2.errors import HTTPError, GeoIP2Error
273
274
def lookup_with_retry(ip_address, max_retries=3, retry_delay=1.0):
275
"""
276
Lookup IP with retry logic for transient errors.
277
"""
278
for attempt in range(max_retries):
279
try:
280
with geoip2.webservice.Client(42, 'license_key') as client:
281
return client.city(ip_address)
282
283
except HTTPError as e:
284
# Retry on server errors (5xx) and rate limiting (429)
285
if e.http_status and (e.http_status >= 500 or e.http_status == 429):
286
if attempt < max_retries - 1:
287
print(f"Server error {e.http_status}, retrying in {retry_delay}s...")
288
time.sleep(retry_delay)
289
retry_delay *= 2 # Exponential backoff
290
continue
291
raise
292
293
except GeoIP2Error:
294
# Don't retry on client errors
295
raise
296
297
# If we get here, all retries failed
298
raise HTTPError("Max retries exceeded")
299
```
300
301
### Logging Error Details
302
303
```python
304
import logging
305
import geoip2.webservice
306
from geoip2.errors import GeoIP2Error, HTTPError
307
308
# Configure logging
309
logging.basicConfig(level=logging.INFO)
310
logger = logging.getLogger(__name__)
311
312
def lookup_with_logging(ip_address):
313
try:
314
with geoip2.webservice.Client(42, 'license_key') as client:
315
response = client.city(ip_address)
316
logger.info(f"Successfully looked up {ip_address}: {response.country.name}")
317
return response
318
319
except HTTPError as e:
320
logger.error(f"HTTP error for {ip_address}: {e.http_status} {e.uri}")
321
logger.debug(f"Response content: {e.decoded_content}")
322
raise
323
324
except GeoIP2Error as e:
325
logger.error(f"GeoIP2 error for {ip_address}: {type(e).__name__}: {e}")
326
raise
327
328
except Exception as e:
329
logger.error(f"Unexpected error for {ip_address}: {type(e).__name__}: {e}")
330
raise
331
```
332
333
## Common Error Scenarios
334
335
### Web Service Errors
336
337
- **AddressNotFoundError**: Private IPs (10.x.x.x, 192.168.x.x, 127.x.x.x), invalid IPs
338
- **AuthenticationError**: Wrong account ID, expired license key, missing credentials
339
- **OutOfQueriesError**: Monthly query limit exceeded, payment failure
340
- **PermissionRequiredError**: Accessing Insights without subscription
341
- **HTTPError 429**: Rate limiting (too many requests)
342
- **HTTPError 5xx**: Server-side errors, maintenance windows
343
344
### Database Errors
345
346
- **AddressNotFoundError**: IP not in database coverage, private IP ranges
347
- **FileNotFoundError**: Database file path incorrect or file deleted
348
- **PermissionError**: Insufficient file system permissions
349
- **maxminddb.InvalidDatabaseError**: Corrupted database file
350
- **TypeError**: Wrong database type for lookup method (e.g., calling city() on ASN database)
351
352
### Network Errors
353
354
- **HTTPError**: DNS resolution failure, network connectivity issues
355
- **Timeout errors**: Network timeout, slow server response
356
- **SSL errors**: Certificate validation failure, TLS handshake errors