Documentation
SDK Reference: Exceptions
Exception hierarchy and error types in the SDK
Exception Handling
All SDK exceptions inherit from ScopixError and are importable directly from scopix, e.g. from scopix import AuthenticationError, RateLimitError, ScopixError.
Exception Hierarchy
ScopixError (base)├── AuthenticationError # Invalid API key (401)├── ScopixPermissionError # Insufficient permissions (403)├── ResourceNotFoundError # Resource not found (404)├── ValidationError # Invalid request data (400/422)├── QuotaExceededError # Upload/API quota exceeded├── PaymentRequiredError # Subscription payment past due (402)├── RateLimitError # Too many requests (429)├── ScopixTimeoutError # Operation timed out├── ServerError # Server-side error (5xx)├── ScopixConnectionError # Network connection failed├── CircuitBreakerError # Circuit breaker open├── UploadError # Image upload operation failed├── DescriptionError # Description generation failed├── ChatError # Chat operation failed├── DocumentProcessingError # Document processing failed├── CloudStorageError # Cloud storage job failed├── S3ConnectorError # S3 connector job failed├── VideoUploadError # Video upload failed├── VideoAnalysisError # Video analysis failed└── SSEStreamError # SSE streaming failedBase Exception
ScopixError
Base exception for all SDK errors
class ScopixError(Exception): code: str # Error code (e.g., "AUTH_ERROR") message: str # Human-readable message details: dict[str, Any] # Additional context
def __init__( self, code: str, message: str, *, details: Optional[dict[str, Any]] = None, ) -> None: ...Example
from scopix import ScopixError
try: result = await client.files.upload_batch("image.jpg")except ScopixError as e: print(f"Error code: {e.code}") print(f"Message: {e.message}") print(f"Details: {e.details}")Authentication Errors
AuthenticationError
Invalid or missing API key (HTTP 401)
class AuthenticationError(ScopixError): # code = "AUTH_ERROR" def __init__(self, message: str = "Authentication failed") -> None: ...Example
from scopix import AuthenticationError
try: result = await client.files.upload_batch("image.jpg")except AuthenticationError: print("Invalid API key - check your credentials")ScopixPermissionError
Insufficient permissions (HTTP 403)
class ScopixPermissionError(ScopixError): # code = "PERMISSION_DENIED" def __init__(self, message: str = "Permission denied") -> None: ...Rate Limiting Errors
RateLimitError
API rate limit exceeded (HTTP 429)
class RateLimitError(ScopixError): # code = "RATE_LIMIT" retry_after: Optional[int] # Seconds to wait before retrying limit: Optional[int] # Max requests allowed remaining: Optional[int] # Requests remaining (always 0) reset: Optional[int] # Unix timestamp when limit resets
def __init__( self, message: str = "Rate limit exceeded", *, retry_after: Optional[int] = None, limit: Optional[int] = None, remaining: Optional[int] = None, reset: Optional[int] = None, ) -> None: ...Example
import asynciofrom scopix import RateLimitError
try: result = await client.files.upload_batch("image.jpg")except RateLimitError as e: print(f"Rate limited: {e.message}") print(f"Retry after: {e.retry_after} seconds") await asyncio.sleep(e.retry_after or 5) result = await client.files.upload_batch("image.jpg")QuotaExceededError
Upload or processing quota exceeded
class QuotaExceededError(ScopixError): # code = "QUOTA_EXCEEDED" # details contains: available, limit
def __init__( self, message: str, *, available: int = 0, limit: int = 0, partial_results: Any = None, ) -> None: ...Example
from scopix import QuotaExceededError
try: result = await client.files.upload_batch("image.jpg")except QuotaExceededError as e: print(f"Quota exceeded: {e.message}") print(f"Available: {e.details.get('available')}") print(f"Limit: {e.details.get('limit')}")Validation Errors
ValidationError
Request validation failed (HTTP 400/422)
class ValidationError(ScopixError): # code = "VALIDATION_ERROR"
def __init__( self, message: str, *, details: Optional[dict[str, Any]] = None, ) -> None: ...ResourceNotFoundError
Requested resource not found (HTTP 404)
class ResourceNotFoundError(ScopixError): # code = "NOT_FOUND" # details contains: resource_type, resource_id
def __init__( self, resource_type: str, resource_id: str, *, message: Optional[str] = None, details: Optional[dict[str, Any]] = None, ) -> None: ...Example
from scopix import ResourceNotFoundError
try: details = await client.files.get(file_id="nonexistent")except ResourceNotFoundError as e: print(f"Not found: {e.message}") print(f"Resource type: {e.details.get('resource_type')}") print(f"Resource ID: {e.details.get('resource_id')}")Network Errors
ScopixTimeoutError
Operation timed out
class ScopixTimeoutError(ScopixError): # code = "TIMEOUT" last_result: Optional[Any] # Last result before timeout
def __init__( self, message: str = "Operation timed out", *, last_result: Optional[Any] = None, ) -> None: ...ScopixConnectionError
Network connection failed
class ScopixConnectionError(ScopixError): # code = "CONNECTION_ERROR" def __init__(self, message: str = "Connection failed") -> None: ...ServerError
Server-side error (HTTP 5xx)
class ServerError(ScopixError): # code = "SERVER_ERROR" def __init__(self, message: str = "Server error") -> None: ...CircuitBreakerError
Service temporarily unavailable due to repeated failures. Retry after the specified delay.
class CircuitBreakerError(ScopixError): # code = "CIRCUIT_OPEN" retry_after: float # Seconds to wait before retryingOperation Errors
UploadError
File upload operation failed
class UploadError(ScopixError): # code = "UPLOAD_ERROR" # details contains: filename, stage
def __init__( self, message: str, *, filename: Optional[str] = None, stage: Optional[str] = None, # Which step failed session_id: Optional[str] = None, partial_results: Any = None, ) -> None: ...Example
from scopix import UploadError
try: result = await client.files.upload_batch("image.jpg")except UploadError as e: print(f"Upload failed: {e.message}") print(f"Filename: {e.details.get('filename')}") print(f"Stage: {e.details.get('stage')}")DescriptionError
Description generation failed
class DescriptionError(ScopixError): # code = "DESCRIPTION_ERROR" # details contains: image_id, status
def __init__( self, message: str, *, image_id: Optional[str] = None, status: Optional[str] = None, ) -> None: ...Note
AI descriptions run asynchronously after the upload call returns. Check result.description_status and result.description_error, or call results.raise_on_failures() on a BatchUploadResults to surface failures.
DocumentProcessingError
Document processing operation failed
class DocumentProcessingError(ScopixError): # code = "DOCUMENT_PROCESSING_ERROR" # details contains: document_id, status
def __init__( self, message: str, *, document_id: Optional[str] = None, status: Optional[str] = None, ) -> None: ...Example
from scopix import DocumentProcessingError
try: await client.files.delete("doc_abc123")except DocumentProcessingError as e: print(f"Cannot process document: {e.message}") print(f"Document ID: {e.details.get('document_id')}")ChatError
Chat operation failed
class ChatError(ScopixError): # code = "CHAT_ERROR" or custom error_code # details contains: session_id
def __init__( self, message: str, *, session_id: Optional[str] = None, error_code: Optional[str] = None, ) -> None: ...CloudStorageError
Cloud storage import/export job failed
class CloudStorageError(ScopixError): # code = "CLOUD_STORAGE_ERROR" # details contains: job_id, job_status
def __init__( self, message: str, *, job_id: Optional[str] = None, job_status: Optional[str] = None, ) -> None: ...Example
from scopix import CloudStorageError
try: job = await client.cloud_storage.import_and_wait( connection_id="conn_abc123", files=files, )except CloudStorageError as e: print(f"Job failed: {e.message}") print(f"Job ID: {e.details.get('job_id')}") print(f"Status: {e.details.get('job_status')}")S3ConnectorError
S3 connector operation failed
class S3ConnectorError(ScopixError): # code = "S3_CONNECTOR_ERROR" # details contains: job_id, job_status
def __init__( self, message: str, *, job_id: Optional[str] = None, job_status: Optional[str] = None, ) -> None: ...Example
from scopix import S3ConnectorError
try: job = await client.s3_connector.wait_for_job(job_id="job_abc123")except S3ConnectorError as e: print(f"Job failed: {e.message}") print(f"Job ID: {e.details.get('job_id')}") print(f"Status: {e.details.get('job_status')}")VideoUploadError
Multipart video upload failed before the file was fully registered
class VideoUploadError(ScopixError): # code = "VIDEO_UPLOAD_ERROR" # details contains: media_id, stage, partial_chunks
def __init__( self, message: str, *, media_id: Optional[str] = None, stage: Optional[str] = None, # "initiate" | "chunk_upload" | "complete" partial_chunks: int = 0, ) -> None: ...VideoAnalysisError
VLM scene analysis failed — raised by wait_for_completion() when the job ends in failed state
class VideoAnalysisError(ScopixError): # code = "VIDEO_ANALYSIS_ERROR" # details contains: media_id, analysis_job_id, status
def __init__( self, message: str, *, media_id: Optional[str] = None, analysis_job_id: Optional[str] = None, status: Optional[str] = None, ) -> None: ...Example
from scopix import VideoAnalysisError
try: final = await client.video_analysis.wait_for_completion(job_id, timeout=600)except VideoAnalysisError as e: print(f"Analysis failed for video {e.media_id}: {e.message}") # Optionally retry await client.video_analysis.retry(e.analysis_job_id, e.media_id)SSEStreamError
SSE streaming connection failed after reconnection attempts
class SSEStreamError(ScopixError): # code = "SSE_STREAM_ERROR" # Raised when a streaming connection fails after automatic reconnection attemptsError Handling Patterns
Comprehensive Error Handling
from scopix import ( Scopix, AuthenticationError, RateLimitError, QuotaExceededError, ValidationError, ScopixError,)
async def safe_upload(client: Scopix, file): try: return await client.files.upload_batch(file)
except AuthenticationError: print("Invalid API key") raise
except RateLimitError as e: print(f"Rate limited. Retry after {e.retry_after}s") raise
except QuotaExceededError as e: print(f"Quota exceeded: {e.details.get('available')}/{e.details.get('limit')}") raise
except ValidationError as e: print(f"Invalid request: {e.message}") print(f"Details: {e.details}") raise
except ScopixError as e: print(f"API error [{e.code}]: {e.message}") raiseRetry with Exponential Backoff
import asynciofrom scopix import Scopix, RateLimitError, ServerError, ScopixConnectionError
async def upload_with_retry(client: Scopix, file, max_attempts=3): for attempt in range(max_attempts): try: return await client.files.upload_batch(file)
except RateLimitError as e: if attempt < max_attempts - 1: wait = e.retry_after or (2 ** attempt) print(f"Rate limited, waiting {wait}s...") await asyncio.sleep(wait) else: raise
except (ServerError, ScopixConnectionError): if attempt < max_attempts - 1: wait = 2 ** attempt print(f"Transient error, retrying in {wait}s...") await asyncio.sleep(wait) else: raise
