The MyoSapiens SDK uses typed exceptions to help you handle errors gracefully. All exceptions inherit from APIError.
APIError (base exception)
├── AuthenticationError (401)
├── NotFoundError (404)
├── ValidationError (400, 422)
├── RateLimitError (429)
└── ServerError (500-599)
Base exception for all API errors.
from myosdk 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 APIRaised when authentication fails (401 Unauthorized).
from myosdk 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:
Solution:
Raised when a resource is not found (404 Not Found).
from myosdk import NotFoundError
try:
asset = client.assets.get("non-existent-id")
except NotFoundError as e:
print(f"Asset not found: {e.message}")
Common causes:
Solution:
list() methods to find valid IDsRaised when request validation fails (400 Bad Request, 422 Unprocessable Entity).
from myosdk import ValidationError
try:
job = client.jobs.start_retarget(
c3d_asset_id="invalid",
markerset_asset_id="invalid"
)
except ValidationError as e:
print(f"Validation error: {e.message}")
print(f"Details: {e.response_data}")
Common causes:
Solution:
Raised when rate limit is exceeded (429 Too Many Requests).
from myosdk 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 (from Retry-After header)Common causes:
Solution:
retry_after value to wait before retryingRaised when server returns a 5xx error.
from myosdk 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:
Solution:
from myosdk import Client, 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}")
import time
from myosdk 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))
from myosdk import APIError
try:
result = client.jobs.wait(job_id, timeout=300)
if result["status"] == "FAILED":
error = result.get("error", {})
print(f"Job failed: {error.get('message', 'Unknown error')}")
print(f"Error details: {error}")
elif result["status"] == "SUCCEEDED":
print("Job completed successfully!")
output_asset_id = result["output"]["retarget_output_asset_id"]
client.assets.download(output_asset_id, "output.npz")
except TimeoutError:
print("Job did not complete within timeout period")
except APIError as e:
print(f"Error checking job status: {e.message}")
from myosdk import NotFoundError, ValidationError
def safe_start_retarget(c3d_asset_id, markerset_asset_id):
"""Start a retarget job with validation."""
# Validate assets exist
try:
c3d_asset = client.assets.get(c3d_asset_id)
if c3d_asset["status"] != "completed":
raise ValidationError("C3D asset upload not completed")
markerset_asset = client.assets.get(markerset_asset_id)
if markerset_asset["status"] != "completed":
raise ValidationError("Markerset asset upload not completed")
except NotFoundError as e:
print(f"Asset not found: {e.message}")
return None
# Start job
try:
return client.jobs.start_retarget(
c3d_asset_id=c3d_asset_id,
markerset_asset_id=markerset_asset_id
)
except ValidationError as e:
print(f"Invalid job parameters: {e.message}")
return None
import os
import time
from myosdk import (
Client,
APIError,
AuthenticationError,
NotFoundError,
ValidationError,
RateLimitError,
ServerError
)
def process_retarget(c3d_path, markerset_path):
"""Complete retarget workflow with comprehensive error handling."""
try:
# Initialize client
client = Client(api_key=os.getenv("MYOSDK_API_KEY"))
# Upload C3D file
try:
c3d_asset = client.assets.upload_file(c3d_path)
print(f"Uploaded C3D: {c3d_asset['asset_id']}")
except ValidationError as e:
print(f"C3D upload validation error: {e.message}")
return None
except APIError as e:
print(f"C3D upload failed: {e.message}")
return None
# Upload markerset
try:
markerset_asset = client.assets.upload_file(markerset_path)
print(f"Uploaded markerset: {markerset_asset['asset_id']}")
except ValidationError as e:
print(f"Markerset upload validation error: {e.message}")
return None
except APIError as e:
print(f"Markerset upload failed: {e.message}")
return None
# Start retarget job
try:
job = client.jobs.start_retarget(
c3d_asset_id=c3d_asset["asset_id"],
markerset_asset_id=markerset_asset["asset_id"]
)
print(f"Started job: {job['job_id']}")
except ValidationError as e:
print(f"Job creation validation error: {e.message}")
return None
except APIError as e:
print(f"Job creation failed: {e.message}")
return None
# Wait for completion
try:
result = client.jobs.wait(job["job_id"], timeout=600)
if result["status"] == "FAILED":
error = result.get("error", {})
print(f"Job failed: {error.get('message', 'Unknown error')}")
return None
if result["status"] != "SUCCEEDED":
print(f"Job ended with unexpected status: {result['status']}")
return None
# Download result
output_asset_id = result["output"]["retarget_output_asset_id"]
client.assets.download(output_asset_id, "output.npz")
print("Download complete!")
return "output.npz"
except TimeoutError:
print("Job did not complete within timeout period")
return None
except APIError as e:
print(f"Error during job execution: {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()