Error Handling
This guide explains how to handle various types of errors you might encounter when using the Nanonets API.
Common Error Types
1. Authentication Errors (401)
{
"code": "unauthorized",
"message": "Invalid API key",
"details": {
"error": "Authentication failed"
}
}
How to handle:
import requests
from requests.auth import HTTPBasicAuth
def make_api_request(url, api_key):
try:
response = requests.get(url, auth=HTTPBasicAuth(api_key, ''))
response.raise_for_status()
return response.json()
except requests.exceptions.HTTPError as e:
if e.response.status_code == 401:
print("Authentication failed. Please check your API key.")
# Implement key rotation or notify admin
raise
2. Rate Limiting (429)
{
"code": "rate_limit_exceeded",
"message": "Rate limit exceeded",
"details": {
"retry_after": 60
}
}
How to handle:
import time
import requests
from requests.auth import HTTPBasicAuth
def make_api_request_with_retry(url, api_key, max_retries=3):
for attempt in range(max_retries):
try:
response = requests.get(url, auth=HTTPBasicAuth(api_key, ''))
response.raise_for_status()
return response.json()
except requests.exceptions.HTTPError as e:
if e.response.status_code == 429:
retry_after = int(e.response.json()['details']['retry_after'])
print(f"Rate limited. Waiting {retry_after} seconds...")
time.sleep(retry_after)
continue
raise
raise Exception("Max retries exceeded")
3. Bad Request (400)
{
"code": "invalid_request",
"message": "Invalid file format",
"details": {
"allowed_formats": ["pdf", "jpg", "png"]
}
}
How to handle:
def validate_file(file_path):
allowed_extensions = ['.pdf', '.jpg', '.png']
if not any(file_path.lower().endswith(ext) for ext in allowed_extensions):
raise ValueError(f"File must be one of: {', '.join(allowed_extensions)}")
def process_document(file_path, api_key, workflow_id):
try:
validate_file(file_path)
url = f"https://app.nanonets.com/api/v4/workflows/{workflow_id}/documents"
files = {'file': open(file_path, 'rb')}
response = requests.post(url, files=files, auth=HTTPBasicAuth(api_key, ''))
response.raise_for_status()
return response.json()
except ValueError as e:
print(f"Validation error: {e}")
raise
except requests.exceptions.HTTPError as e:
if e.response.status_code == 400:
error_details = e.response.json()
print(f"Bad request: {error_details['message']}")
print(f"Details: {error_details['details']}")
raise
4. Server Errors (5xx)
{
"code": "internal_error",
"message": "An unexpected error occurred",
"details": {
"request_id": "abc123"
}
}
How to handle:
def make_api_request_with_fallback(url, api_key):
try:
response = requests.get(url, auth=HTTPBasicAuth(api_key, ''))
response.raise_for_status()
return response.json()
except requests.exceptions.HTTPError as e:
if 500 <= e.response.status_code < 600:
print(f"Server error: {e.response.json()['message']}")
print(f"Request ID: {e.response.json()['details']['request_id']}")
# Log the error and notify support
# Implement fallback logic if available
raise
Best Practices
- Implement Proper Logging
import logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
def log_api_error(error, context=None):
logger.error(f"API Error: {error}")
if context:
logger.error(f"Context: {context}")
# Add error to monitoring system
- Use Circuit Breakers
from circuitbreaker import circuit
@circuit(failure_threshold=5, recovery_timeout=60)
def make_api_request(url, api_key):
response = requests.get(url, auth=HTTPBasicAuth(api_key, ''))
response.raise_for_status()
return response.json()
- Implement Retry with Exponential Backoff
import time
from functools import wraps
def retry_with_backoff(retries=5, backoff_in_seconds=1):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
x = 0
while True:
try:
return func(*args, **kwargs)
except Exception as e:
if x == retries:
raise
sleep_time = (backoff_in_seconds * 2 ** x +
random.uniform(0, 1))
time.sleep(sleep_time)
x += 1
return wrapper
return decorator
@retry_with_backoff()
def make_api_request(url, api_key):
response = requests.get(url, auth=HTTPBasicAuth(api_key, ''))
response.raise_for_status()
return response.json()
- Handle Timeouts
def make_api_request_with_timeout(url, api_key, timeout=30):
try:
response = requests.get(
url,
auth=HTTPBasicAuth(api_key, ''),
timeout=timeout
)
response.raise_for_status()
return response.json()
except requests.exceptions.Timeout:
print(f"Request timed out after {timeout} seconds")
# Implement fallback or retry logic
raise
Monitoring and Alerting
Set up monitoring for:
- Error rates
- Response times
- Rate limit usage
- Authentication failures
Configure alerts for:
- High error rates
- Repeated authentication failures
- Rate limit exhaustion
- Server errors
Need Help?
- Check the API Reference
- Join our Discord community
- Contact support