Skip to main content

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

  1. 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
  1. 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()
  1. 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()
  1. 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

  1. Set up monitoring for:

    • Error rates
    • Response times
    • Rate limit usage
    • Authentication failures
  2. Configure alerts for:

    • High error rates
    • Repeated authentication failures
    • Rate limit exhaustion
    • Server errors

Need Help?