Error Handling

Complete guide to handling API errors and error codes.


Error Response Format

All API errors follow a consistent format:

{
  "error": "error_code",
  "code": "ERROR_CODE",
  "message": "Human-readable error description",
  "details": {
    "field": "additional context"
  }
}

HTTP Status Codes

Archivus uses standard HTTP status codes:

Status Code Meaning Description
200 OK Request succeeded
201 Created Resource created successfully
400 Bad Request Invalid request data
401 Unauthorized Authentication required or failed
403 Forbidden Insufficient permissions
404 Not Found Resource not found
409 Conflict Resource conflict (e.g., duplicate)
413 Payload Too Large Request body too large
415 Unsupported Media Type Invalid file type
429 Too Many Requests Rate limit exceeded
500 Internal Server Error Server error
503 Service Unavailable Service temporarily unavailable

Common Error Codes

Authentication Errors

UNAUTHORIZED

Status: 401 Unauthorized

{
  "error": "unauthorized",
  "code": "UNAUTHORIZED",
  "message": "Authentication required"
}

Causes:

  • Missing authentication header
  • Invalid or expired token
  • Invalid API key

Solution:

  • Check authentication headers
  • Refresh expired tokens
  • Verify API key is correct

INVALID_CREDENTIALS

Status: 401 Unauthorized

{
  "error": "invalid_credentials",
  "code": "INVALID_CREDENTIALS",
  "message": "Invalid email or password"
}

Solution:

  • Verify email and password
  • Check for typos
  • Ensure account exists

TOKEN_EXPIRED

Status: 401 Unauthorized

{
  "error": "token_expired",
  "code": "TOKEN_EXPIRED",
  "message": "JWT token has expired"
}

Solution:

  • Refresh token using refresh endpoint
  • Re-authenticate if refresh token expired

CSRF_TOKEN_REQUIRED

Status: 403 Forbidden

{
  "error": "csrf_token_required",
  "code": "CSRF_TOKEN_REQUIRED",
  "message": "CSRF token is required for this request"
}

Solution:

  • Get CSRF token from /api/v1/auth/csrf-token
  • Include in X-CSRF-Token header

Validation Errors

VALIDATION_ERROR

Status: 400 Bad Request

{
  "error": "validation_error",
  "code": "VALIDATION_ERROR",
  "message": "Request validation failed",
  "details": {
    "field": "email",
    "message": "Invalid email format"
  }
}

Solution:

  • Check request body format
  • Verify required fields are present
  • Validate field formats

MISSING_REQUIRED_FIELD

Status: 400 Bad Request

{
  "error": "missing_required_field",
  "code": "MISSING_REQUIRED_FIELD",
  "message": "Required field 'email' is missing",
  "details": {
    "field": "email"
  }
}

Resource Errors

NOT_FOUND

Status: 404 Not Found

{
  "error": "not_found",
  "code": "NOT_FOUND",
  "message": "Document with ID 'doc_abc123' not found"
}

Solution:

  • Verify resource ID is correct
  • Check if resource was deleted
  • Ensure you have access to the resource

FORBIDDEN

Status: 403 Forbidden

{
  "error": "forbidden",
  "code": "FORBIDDEN",
  "message": "You don't have permission to access this resource"
}

Solution:

  • Check your permissions
  • Verify you’re accessing the correct tenant
  • Contact administrator for access

File Upload Errors

FILE_TOO_LARGE

Status: 413 Payload Too Large

{
  "error": "file_too_large",
  "code": "FILE_TOO_LARGE",
  "message": "File size exceeds maximum limit of 500MB"
}

Solution:

  • Compress file or split into smaller parts
  • Check file size before upload
  • Upgrade plan for larger limits

INVALID_FILE_TYPE

Status: 415 Unsupported Media Type

{
  "error": "invalid_file_type",
  "code": "INVALID_FILE_TYPE",
  "message": "File type not supported"
}

Solution:

  • Check supported file types
  • Convert file to supported format
  • Verify file extension matches content

Rate Limit Errors

RATE_LIMIT_EXCEEDED

Status: 429 Too Many Requests

{
  "error": "rate_limit_exceeded",
  "code": "RATE_LIMIT_EXCEEDED",
  "message": "Rate limit exceeded. Please try again later.",
  "details": {
    "limit": 120,
    "remaining": 0,
    "reset_at": "2025-12-16T10:31:00Z"
  }
}

Solution:

  • Wait until reset_at timestamp
  • Implement exponential backoff
  • Upgrade plan for higher limits
  • Reduce request frequency

Server Errors

INTERNAL_ERROR

Status: 500 Internal Server Error

{
  "error": "internal_error",
  "code": "INTERNAL_ERROR",
  "message": "An internal error occurred"
}

Solution:

  • Retry request after a delay
  • Check API status page
  • Contact support if persistent

SERVICE_UNAVAILABLE

Status: 503 Service Unavailable

{
  "error": "service_unavailable",
  "code": "SERVICE_UNAVAILABLE",
  "message": "Service temporarily unavailable"
}

Solution:

  • Retry after a delay
  • Check API status
  • Implement retry logic

Error Handling Best Practices

Always Check Status Codes

response = requests.get(url, headers=headers)

if response.status_code == 200:
    data = response.json()
elif response.status_code == 401:
    # Handle authentication error
    refresh_token()
elif response.status_code == 429:
    # Handle rate limit
    wait_and_retry(response.headers.get('Retry-After'))
else:
    # Handle other errors
    error = response.json()
    log_error(error)

Implement Retry Logic

import time
from requests.exceptions import RequestException

def make_request_with_retry(url, headers, max_retries=3):
    for attempt in range(max_retries):
        try:
            response = requests.get(url, headers=headers)
            
            if response.status_code == 429:
                # Rate limited - wait and retry
                retry_after = int(response.headers.get('Retry-After', 60))
                time.sleep(retry_after)
                continue
            
            if response.status_code >= 500:
                # Server error - retry with exponential backoff
                wait_time = 2 ** attempt
                time.sleep(wait_time)
                continue
            
            return response
            
        except RequestException as e:
            if attempt == max_retries - 1:
                raise
            time.sleep(2 ** attempt)
    
    return None

Handle Specific Errors

try:
    response = requests.post(url, json=data, headers=headers)
    response.raise_for_status()
except requests.exceptions.HTTPError as e:
    error = response.json()
    error_code = error.get('code')
    
    if error_code == 'NOT_FOUND':
        # Handle not found
        pass
    elif error_code == 'VALIDATION_ERROR':
        # Handle validation error
        details = error.get('details', {})
        print(f"Validation error: {details}")
    elif error_code == 'RATE_LIMIT_EXCEEDED':
        # Handle rate limit
        reset_at = error.get('details', {}).get('reset_at')
        wait_until(reset_at)

Error Code Reference

Authentication (401)

  • UNAUTHORIZED - Authentication required
  • INVALID_CREDENTIALS - Invalid email/password
  • TOKEN_EXPIRED - Token expired
  • INVALID_API_KEY - Invalid API key

Authorization (403)

  • FORBIDDEN - Insufficient permissions
  • CSRF_TOKEN_REQUIRED - CSRF token missing

Validation (400)

  • VALIDATION_ERROR - Request validation failed
  • MISSING_REQUIRED_FIELD - Required field missing
  • INVALID_QUERY - Invalid search query

Not Found (404)

  • NOT_FOUND - Resource not found
  • DOCUMENT_NOT_FOUND - Document not found
  • FOLDER_NOT_FOUND - Folder not found

Conflict (409)

  • DUPLICATE_RESOURCE - Resource already exists
  • FOLDER_NOT_EMPTY - Folder contains documents

Rate Limits (429)

  • RATE_LIMIT_EXCEEDED - Too many requests

Server Errors (500)

  • INTERNAL_ERROR - Internal server error
  • SERVICE_UNAVAILABLE - Service unavailable

Next Steps


Questions? Check the FAQ or contact support@ubiship.com