Reference
Error Handling
Exception types and error handling in the MyoSapiens SDK.
The MyoSapiens SDK uses typed exceptions to help you handle errors gracefully. All exceptions inherit from APIError.
Exception Hierarchy
APIError (base exception)
├── AuthenticationError (401)
├── NotFoundError (404)
├── ValidationError (400, 422)
├── RateLimitError (429)
└── ServerError (500-599)
Exception Types
APIError
Base exception for all API errors.
from myosdk.exceptions import ApiError
try:
asset = client.assets.get("invalid-id")
except ApiError as e:
print(f"Error: {e.message}")
print(f"Status code: {e.status_code}")
print(f"Response data: {e.response_data}")
Attributes:
message(str) - Error messagestatus_code(int | None) - HTTP status coderesponse_data(dict | None) - Full error response from API
AuthenticationError
Raised when authentication fails (401 Unauthorized).
from myosdk.exceptions import AuthenticationError
try:
client = Client(api_key="invalid_key")
assets = client.assets.list()
except AuthenticationError as e:
print("Authentication failed. Check your API key.")
Common causes:
- Invalid or expired API key
- Missing API key
- API key revoked
Solution:
- Verify your API key at dev.myolab.ai
- Ensure you're using the correct API key format
- Check that your API key hasn't been revoked
NotFoundError
Raised when a resource is not found (404 Not Found).
from myosdk.exceptions import NotFoundError
try:
asset = client.assets.get("non-existent-id")
except NotFoundError as e:
print(f"Asset not found: {e.message}")
Common causes:
- Invalid asset ID, job ID, or character ID
- Resource was deleted
- Resource belongs to a different tenant
Solution:
- Verify the resource ID is correct
- Check that the resource exists and belongs to your tenant
- Use
list()methods to find valid IDs
ValidationError
Raised when request validation fails (400 Bad Request, 422 Unprocessable Entity).
from myosdk.exceptions import ValidationError
try:
result = client.retarget(
tracker="invalid",
markerset="invalid",
)
except ValidationError as e:
print(f"Validation error: {e.message}")
print(f"Details: {e.response_data}")
Common causes:
- Missing required parameters
- Invalid parameter values
- Asset has wrong purpose for the operation
- Asset upload not completed
Solution:
- Check that all required parameters are provided
- Verify parameter types and values
- Ensure assets are in the correct state (e.g., upload completed)
RateLimitError
Raised when rate limit is exceeded (429 Too Many Requests).
from myosdk.exceptions import RateLimitError
import time
try:
for i in range(1000):
assets = client.assets.list()
except RateLimitError as e:
print(f"Rate limit exceeded: {e.message}")
if e.retry_after:
print(f"Retry after {e.retry_after} seconds")
time.sleep(e.retry_after)
Attributes:
retry_after(int | None) - Seconds to wait before retrying (fromRetry-Afterheader)
Common causes:
- Too many requests in a short time period
- Exceeding your plan's rate limits
Solution:
- Implement exponential backoff
- Use the
retry_aftervalue to wait before retrying - Consider upgrading your plan for higher rate limits
- Batch operations when possible
ServerError
Raised when server returns a 5xx error.
from myosdk.exceptions import ServerError
try:
job = client.jobs.get(job_id)
except ServerError as e:
print(f"Server error: {e.message}")
print(f"Status code: {e.status_code}")
# Retry with exponential backoff
Common causes:
- Temporary server issues
- Service overload
- Internal server errors
Solution:
- Implement retry logic with exponential backoff
- The SDK automatically retries on server errors (up to 3 times)
- If errors persist, contact support@myolab.ai
Error Handling Patterns
Basic Error Handling
from myosdk import Client
from myosdk.exceptions import ApiError, NotFoundError, ValidationError
try:
asset = client.assets.get(asset_id)
except NotFoundError:
print("Asset not found")
except ValidationError as e:
print(f"Invalid request: {e.message}")
except ApiError as e:
print(f"API error: {e.message}")
except Exception as e:
print(f"Unexpected error: {e}")
Retry with Exponential Backoff
import time
from myosdk.exceptions import RateLimitError, ServerError
def retry_with_backoff(func, max_retries=3, initial_delay=1.0):
"""Retry a function with exponential backoff."""
for attempt in range(max_retries):
try:
return func()
except (RateLimitError, ServerError) as e:
if attempt == max_retries - 1:
raise
# Use retry_after if available, otherwise use exponential backoff
if isinstance(e, RateLimitError) and e.retry_after:
delay = e.retry_after
else:
delay = initial_delay * (2 ** attempt)
print(f"Retrying after {delay} seconds...")
time.sleep(delay)
# Usage
asset = retry_with_backoff(lambda: client.assets.get(asset_id))
Handling Job Failures
from myosdk.exceptions import ApiError, JobFailedError, JobTimeoutError
try:
result = client.retarget(
tracker="motion.c3d",
markerset="markerset.xml",
timeout=300,
)
result.download_all("out/")
print("Job completed successfully!")
except JobTimeoutError:
print("Job did not complete within timeout period")
except JobFailedError as e:
print(f"Job failed: {e}")
except ApiError as e:
print(f"Error: {e.message}")
Validating Before Operations
from pathlib import Path
from myosdk.exceptions import NotFoundError, ValidationError
def safe_retarget(tracker, markerset):
"""Run a retarget job with validation."""
try:
# If using asset IDs (not file paths), validate they exist
if isinstance(tracker, str) and not Path(tracker).exists():
client.assets.get(tracker)
if isinstance(markerset, str) and not Path(markerset).exists():
client.assets.get(markerset)
except NotFoundError as e:
print(f"Asset not found: {e.message}")
return None
try:
return client.retarget(tracker=tracker, markerset=markerset)
except ValidationError as e:
print(f"Invalid job parameters: {e.message}")
return None
Best Practices
- Always handle exceptions - Don't let API errors crash your application
- Use specific exception types - Catch specific exceptions for better error handling
- Implement retries - For transient errors (rate limits, server errors), implement retry logic
- Log errors - Log error details for debugging and monitoring
- Validate inputs - Check asset IDs and parameters before making requests
- Check job status - Always check job status before accessing output
Example: Complete Error Handling
import os
from pathlib import Path
from myosdk import Client
from myosdk.exceptions import (
ApiError,
AuthenticationError,
InsufficientCreditsError,
JobFailedError,
JobTimeoutError,
NotFoundError,
ValidationError,
)
def process_retarget(tracker_path, markerset_path, output_dir="out/"):
"""Complete retarget workflow with comprehensive error handling."""
try:
client = Client(api_key=os.getenv("MYO_API_KEY"))
try:
result = client.retarget(
tracker=tracker_path,
markerset=markerset_path,
export_glb=True,
stream_status=True,
output_dir=output_dir,
timeout=600,
)
print(f"Job completed! Processing time: {result.processing_time_seconds}s")
if not output_dir:
result.download_all("out/")
print("Download complete!")
return "out/"
except InsufficientCreditsError as e:
print(f"Insufficient credits: {e}")
return None
except JobTimeoutError:
print("Job did not complete within timeout period")
return None
except JobFailedError as e:
print(f"Job failed: {e}")
return None
except ValidationError as e:
print(f"Validation error: {e.message}")
return None
except ApiError as e:
print(f"API error: {e.message}")
return None
except AuthenticationError:
print("Authentication failed. Check your API key.")
return None
except Exception as e:
print(f"Unexpected error: {e}")
return None
finally:
client.close()
Next Steps
- SDK Reference - Complete SDK documentation
- API Reference - REST API documentation
- Retargeting Tutorial - Complete workflow example