Skip to content

Error Handling

The Konigle SDK provides comprehensive error handling through a structured exception hierarchy. All exceptions inherit from the base KonigleError class, making it easy to catch and handle SDK-specific errors.

Exception Hierarchy

Base Exceptions

  • KonigleError - Base exception for all SDK errors
  • APIError - Base for API-related errors with HTTP context
  • NetworkError - Network connectivity issues
  • KonigleTimeoutError - Request timeout errors

HTTP Status Code Exceptions

  • ValidationError (400) - Request validation failed
  • AuthenticationError (401) - Invalid API key
  • AuthorizationError (403) - Insufficient permissions
  • NotFoundError (404) - Resource not found
  • ConflictError (409) - Resource conflict
  • RateLimitError (429) - Rate limit exceeded
  • ServerError (5xx) - Server-side errors

Basic Error Handling

Catch All SDK Errors

import konigle
from konigle.exceptions import KonigleError

try:
    client = konigle.Client(api_key="your-api-key")
    image = client.images.get("img_123")
except KonigleError as e:
    print(f"SDK error occurred: {e}")
except Exception as e:
    print(f"Unexpected error: {e}")

Handle Specific Errors

from konigle.exceptions import (
    AuthenticationError,
    NotFoundError,
    ValidationError,
    RateLimitError
)

try:
    client = konigle.Client(api_key="your-api-key")
    image = client.images.create(image_data)

except AuthenticationError:
    print("Invalid API key - please check your credentials")

except ValidationError as e:
    print(f"Validation failed: {e}")
    if e.field_errors:
        for field, errors in e.field_errors.items():
            print(f"  {field}: {errors}")

except NotFoundError:
    print("Resource not found")

except RateLimitError as e:
    print(f"Rate limit exceeded: {e}")
    if e.retry_after:
        print(f"Retry after {e.retry_after} seconds")

Advanced Error Handling

API Error Details

All APIError exceptions include additional context:

from konigle.exceptions import APIError

try:
    client.images.create(invalid_data)
except APIError as e:
    print(f"Status Code: {e.status_code}")
    print(f"Message: {e}")
    print(f"Response: {e.response}")

Validation Error Details

ValidationError provides field-specific error information:

from konigle.exceptions import ValidationError

try:
    image_data = ImageCreate(
        name="",  # Invalid: empty name
        image="invalid.txt"  # Invalid: not an image
    )
except ValidationError as e:
    print(f"General error: {e}")

    # Access field-specific errors
    for field, errors in e.field_errors.items():
        print(f"Field '{field}': {errors}")

Rate Limit Handling

Handle rate limits with automatic retry:

import time
from konigle.exceptions import RateLimitError

def create_image_with_retry(client, image_data, max_retries=3):
    for attempt in range(max_retries):
        try:
            return client.images.create(image_data)
        except RateLimitError as e:
            if attempt == max_retries - 1:
                raise  # Re-raise on final attempt

            wait_time = e.retry_after or 60  # Default to 60s
            print(f"Rate limited. Waiting {wait_time} seconds...")
            time.sleep(wait_time)

Network Error Handling

Handle connectivity issues:

from konigle.exceptions import NetworkError, KonigleTimeoutError

def robust_api_call(client, operation_func, *args, **kwargs):
    max_retries = 3
    base_delay = 1

    for attempt in range(max_retries):
        try:
            return operation_func(*args, **kwargs)

        except KonigleTimeoutError:
            print(f"Request timed out (attempt {attempt + 1})")
            if attempt == max_retries - 1:
                raise
            time.sleep(base_delay * (2 ** attempt))

        except NetworkError:
            print(f"Network error (attempt {attempt + 1})")
            if attempt == max_retries - 1:
                raise
            time.sleep(base_delay * (2 ** attempt))

# Usage
try:
    result = robust_api_call(
        client, 
        client.images.create, 
        image_data
    )
except KonigleError as e:
    print(f"Failed after retries: {e}")

Practical Patterns

Context Manager with Error Handling

from konigle.exceptions import KonigleError

class SafeKonigleClient:
    def __init__(self, api_key):
        self.api_key = api_key
        self.client = None

    def __enter__(self):
        try:
            self.client = konigle.Client(api_key=self.api_key)
            return self.client
        except AuthenticationError:
            print("Authentication failed")
            raise
        except KonigleError as e:
            print(f"Client initialization failed: {e}")
            raise

    def __exit__(self, exc_type, exc_val, exc_tb):
        if self.client:
            self.client.close()

# Usage
try:
    with SafeKonigleClient("your-api-key") as client:
        images = client.images.list()
except KonigleError:
    print("Operation failed")

Async Error Handling

import asyncio
from konigle.exceptions import KonigleError

async def safe_async_operation():
    try:
        async with konigle.AsyncClient(api_key="your-api-key") as client:
            image = await client.images.create(image_data)
            return image

    except ValidationError as e:
        print(f"Validation error: {e}")
        return None

    except RateLimitError as e:
        print(f"Rate limited: {e}")
        if e.retry_after:
            await asyncio.sleep(e.retry_after)
            # Optionally retry here
        return None

    except KonigleError as e:
        print(f"SDK error: {e}")
        return None

result = asyncio.run(safe_async_operation())

Logging Integration

import logging
from konigle.exceptions import APIError, NetworkError

# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

def logged_api_operation(client, operation_name, operation_func, *args, **kwargs):
    try:
        logger.info(f"Starting {operation_name}")
        result = operation_func(*args, **kwargs)
        logger.info(f"{operation_name} completed successfully")
        return result

    except APIError as e:
        logger.error(
            f"{operation_name} API error: {e} "
            f"(Status: {e.status_code})"
        )
        raise

    except NetworkError as e:
        logger.error(f"{operation_name} network error: {e}")
        raise

    except Exception as e:
        logger.error(f"{operation_name} unexpected error: {e}")
        raise

# Usage
try:
    image = logged_api_operation(
        client,
        "Image Creation",
        client.images.create,
        image_data
    )
except KonigleError:
    # Error already logged
    pass

Error Response Structure

API errors include structured response data:

try:
    client.images.create(invalid_data)
except APIError as e:
    # Response structure varies by error type
    response = e.response

    # Common fields
    if "detail" in response:
        print(f"Detail: {response['detail']}")

    if "errors" in response:
        for error in response["errors"]:
            print(f"Error: {error}")

    # Validation-specific fields
    if isinstance(e, ValidationError):
        for field, field_errors in e.field_errors.items():
            print(f"Field {field}: {field_errors}")

Best Practices

  1. Always catch KonigleError for SDK-specific error handling
  2. Handle authentication early - check API key validity on startup
  3. Implement retry logic for rate limits and network errors
  4. Log errors appropriately with sufficient context
  5. Validate data locally before API calls when possible
  6. Use specific exceptions for targeted error handling
  7. Provide user-friendly messages while preserving technical details for debugging