Skip to content

Error Handling

Exception Hierarchy

SiloError                          Base for all SDK errors
├── AuthenticationError             Token rejected by the API
│   └── InvalidTokenError           Specific: token format or value invalid
├── ConfigurationError              Missing or invalid config (before any network call)
├── ValidationError                 Invalid parameter values
├── RateLimitError                  Too many requests
├── BrowsingAPIError                BrowsingAPI-specific errors
│   └── ContextNotFoundError        Context ID doesn't exist
├── UserManagementAPIError          UserManagementAPI-specific errors
│   └── UserNotFoundError           Username doesn't exist
├── OrgManagementAPIError           OrgManagementAPI-specific errors
│   └── OrgNotFoundError            Org slug doesn't exist
├── FileAPIError                    FileAPI-specific errors
│   └── FileNotFoundError           File ID doesn't exist (shadows builtins.FileNotFoundError)
├── LogExtractionAPIError           LogExtractionAPI-specific errors
├── HarvesterAPIError               HarvesterAPI-specific errors
│   └── TaskNotFoundError           Task ID doesn't exist
├── InsufficientPermissionsError    Token lacks required scope
└── QuotaExceededError              Org quota limit hit

Basic Exception Handling

Import from the top-level module

All exceptions can be imported from silo_sdk for convenience:

from silo_sdk import SiloError, BrowsingAPIError, ContextNotFoundError

Always catch the most specific exception first:

from silo_sdk import (
    BrowsingAPI,
    BrowsingAPIError,
    ContextNotFoundError,
    AuthenticationError,
    ConfigurationError,
    ValidationError,
)

try:
    browsing = BrowsingAPI(config)
    info = browsing.get_context("some_context_id")

except ContextNotFoundError:
    print("Context does not exist or has already been deleted")

except AuthenticationError as e:
    print(f"Token rejected: {e}")

except BrowsingAPIError as e:
    print(f"API error: {e}")
    if e.status_code:
        print(f"  HTTP {e.status_code}")

except ConfigurationError as e:
    print(f"Configuration problem: {e}")

Exception Attributes

All SiloError subclasses carry these attributes:

Attribute Type Description
message str Human-readable error description
status_code int \| None HTTP status code (if applicable)
response_data dict \| None Raw API response body (if available)
request_id str \| None Request ID for support escalation
except BrowsingAPIError as e:
    print(f"Error: {e.message}")
    print(f"Status: {e.status_code}")
    print(f"Request ID: {e.request_id}")  # include in support tickets

Common Error Scenarios

Scenario Exception Resolution
Token not in config ConfigurationError Add token to .env or config file
Token expired/invalid InvalidTokenError Rotate the token
Wrong token for API module InsufficientPermissionsError Use the correct token type
Invalid parameter values ValidationError Check method parameter docs
Resource already deleted ContextNotFoundError, UserNotFoundError, etc. Check resource existence first
Org quota hit QuotaExceededError Contact your Authentic8 admin

Error Handling in Flows

For multi-step flows (create → use → cleanup), handle errors at each step and ensure cleanup runs:

context_id = None
try:
    context_id = browsing.create_context(url="https://example.com", username="user@org.com")
    # ... do something with the context ...
except BrowsingAPIError as e:
    print(f"Operation failed: {e}")
finally:
    if context_id:
        try:
            browsing.delete_context(context_id)
        except ContextNotFoundError:
            pass  # already gone