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

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

Base Exception

ScopixError

Base exception for all SDK errors

python
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

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

python
class AuthenticationError(ScopixError):
# code = "AUTH_ERROR"
def __init__(self, message: str = "Authentication failed") -> None: ...

Example

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

python
class ScopixPermissionError(ScopixError):
# code = "PERMISSION_DENIED"
def __init__(self, message: str = "Permission denied") -> None: ...

Rate Limiting Errors

RateLimitError

API rate limit exceeded (HTTP 429)

python
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

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")
await asyncio.sleep(e.retry_after or 5)
result = await client.files.upload_batch("image.jpg")

QuotaExceededError

Upload or processing quota exceeded

python
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

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')}")

Validation Errors

ValidationError

Request validation failed (HTTP 400/422)

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

python
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

python
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

python
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

python
class ScopixConnectionError(ScopixError):
# code = "CONNECTION_ERROR"
def __init__(self, message: str = "Connection failed") -> None: ...

ServerError

Server-side error (HTTP 5xx)

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

python
class CircuitBreakerError(ScopixError):
# code = "CIRCUIT_OPEN"
retry_after: float # Seconds to wait before retrying

Operation Errors

UploadError

File upload operation failed

python
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

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')}")

DescriptionError

Description generation failed

python
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

python
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

python
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

python
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

python
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

python
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

python
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

python
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

python
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

python
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

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

python
class SSEStreamError(ScopixError):
# code = "SSE_STREAM_ERROR"
# Raised when a streaming connection fails after automatic reconnection attempts

Error Handling Patterns

Comprehensive Error Handling

python
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}")
raise

Retry with Exponential Backoff

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):
if attempt < max_attempts - 1:
wait = 2 ** attempt
print(f"Transient error, retrying in {wait}s...")
await asyncio.sleep(wait)
else:
raise