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

python
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

python
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 failed

Exception Details

ScopixError (Base)

All SDK exceptions inherit from this

python
class ScopixError(Exception):
code: str # Error code (e.g., "AUTH_ERROR")
message: str # Human-readable message
details: dict[str, Any] # Additional context

AuthenticationError

Invalid or missing API key

python
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 valid

RateLimitError

API rate limit exceeded

python
import asyncio
from 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

python
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 reset

ValidationError

Invalid request parameters

python
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 parameters

ResourceNotFoundError

Requested resource doesn't exist

python
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.details

ScopixTimeoutError

Operation timed out

python
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 retry

UploadError

Upload operation failed

python
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

python
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

python
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

python
from scopix import DescriptionError
results = await client.files.upload_batch(files)
# Check for failures
if 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 failures
try:
results.raise_on_failures() # Returns self if no failures
except 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

python
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

python
import asyncio
from 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:
raise

Graceful Degradation

Handle failures gracefully

python
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,
}