Documentation
Error Handling
Handle errors gracefully with typed exceptions
Imports
The SDK provides specific exception types for different error conditions. Import them directly from scopix, e.g. from scopix import AuthenticationError, RateLimitError, ScopixError.
Basic Error Handling
Catch and handle common errors
from scopix import ( AuthenticationError, RateLimitError, QuotaExceededError, ValidationError, ScopixError,)
try: result = await client.files.upload_batch("image.jpg")except AuthenticationError: print("Invalid API key")except RateLimitError as e: print(f"Rate limited. Retry after {e.retry_after} seconds")except QuotaExceededError as e: print(f"Quota exceeded: {e.details.get('available')}/{e.details.get('limit')} available")except ValidationError as e: print(f"Invalid request: {e.message}") print(f"Details: {e.details}")except ScopixError as e: print(f"API error: {e.code} - {e.message}")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 (403)├── 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 (repeated failures)├── UploadError # Upload operation failed├── DescriptionError # Description generation failed├── DocumentProcessingError # Document processing failed├── CloudStorageError # Cloud storage operation failed├── S3ConnectorError # S3 connector operation failed├── VideoUploadError # Video upload failed├── VideoAnalysisError # Video analysis failed├── ChatError # Chat operation failed└── SSEStreamError # SSE streaming connection failedException Details
ScopixError (Base)
All SDK exceptions inherit from this
class ScopixError(Exception): code: str # Error code (e.g., "AUTH_ERROR") message: str # Human-readable message details: dict[str, Any] # Additional contextAuthenticationError
Invalid or missing API key
from scopix import AuthenticationError
try: result = await client.files.upload_batch("image.jpg")except AuthenticationError as e: print(f"Authentication failed: {e.message}") # Check your API key and ensure it's validRateLimitError
API rate limit exceeded
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") print(f"Limit: {e.limit}, Remaining: {e.remaining}, Reset: {e.reset}")
# Wait and retry await asyncio.sleep(e.retry_after or 5) result = await client.files.upload_batch("image.jpg")QuotaExceededError
Upload or API quota exceeded
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')}")
# For batch uploads, partial_results contains files uploaded before quota hit if e.partial_results: print(f"Partial results: {e.partial_results.summary()}") # Upgrade plan or wait for quota resetValidationError
Invalid request parameters
from scopix import ValidationError
try: result = await client.files.upload_batch("unsupported_file.bmp")except ValidationError as e: print(f"Validation error: {e.message}") print(f"Details: {e.details}") # Fix the request parametersResourceNotFoundError
Requested resource doesn't exist
from scopix import ResourceNotFoundError
try: details = await client.files.get(file_id="nonexistent")except ResourceNotFoundError as e: print(f"Not found: {e.message}") # Resource type and ID are in e.detailsScopixTimeoutError
Operation timed out
from scopix import ScopixTimeoutError
try: result = await client.files.upload("large_image.jpg")except ScopixTimeoutError as e: print(f"Timed out: {e.message}") # Increase client polling_timeout or retryUploadError
Upload operation failed
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')}")
# session_id can be used to recover results manually if e.session_id: print(f"Session ID: {e.session_id}")
# For batch uploads, partial_results contains files uploaded before failure if e.partial_results: print(f"Partial results: {e.partial_results.summary()}")VideoAnalysisError
Raised by video_analysis.wait_for_completion() when the analysis job ends in a failed state
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 {e.media_id}: {e.message}") # Retry the job await client.video_analysis.retry(e.analysis_job_id, e.media_id)DescriptionError
Description generation failed during upload
from scopix import DescriptionError
result = await client.files.upload("image.jpg")if result.is_failed: raise DescriptionError( f"Description failed: {result.description_error}", image_id=result.image_id, status=result.description_status, )Batch Upload Failure Handling
Inspect failures in a batch without exceptions
from scopix import DescriptionError
results = await client.files.upload_batch(files)
# Check for failuresif results.has_failures: print(f"Summary: {results.summary()}") # "2 succeeded, 1 failed"
for r in results.failed(): print(f"{r.filename}: {r.description_error}") if r.description_is_retryable: print(" -> Can retry")
# Get only retryable failures for r in results.retryable(): print(f"Retryable: {r.image_id}")
# Opt-in to raise DescriptionError on failurestry: results.raise_on_failures() # Returns self if no failuresexcept DescriptionError as e: print(f"Batch had failures: {e.message}")Note
AI descriptions run asynchronously; the upload call returns as soon as bytes are stored. Inspect result.description_status or use results.raise_on_failures() on a BatchUploadResults after polling completes.
ChatError
Chat operation failed
from scopix import ChatError
try: async with client.chat_session() as session: response = await session.send("Query")except ChatError as e: print(f"Chat failed: {e.message}") print(f"Session ID: {e.details.get('session_id')}") print(f"Error code: {e.code}")Retry Pattern
Implement custom retry logic
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) as e: if attempt < max_attempts - 1: wait = 2 ** attempt print(f"Transient error, retrying in {wait}s...") await asyncio.sleep(wait) else: raiseGraceful Degradation
Handle failures gracefully
from scopix import ( Scopix, QuotaExceededError, ScopixTimeoutError, ServerError, ScopixError,)
async def safe_upload(client: Scopix, image): """Upload image with fallback for errors.""" try: result = await client.files.upload(image) return { "success": True, "image_id": result.image_id, "description": result.description, }
except QuotaExceededError: return { "success": False, "error": "quota_exceeded", "message": "API quota exceeded, please try later", }
except (ScopixTimeoutError, ServerError) as e: return { "success": False, "error": "temporary", "message": f"Temporary error: {e.message}", }
except ScopixError as e: return { "success": False, "error": e.code, "message": e.message, }
