Error Handling
The SDK provides structured error handling to help you manage failures gracefully. The approach differs between Python and TypeScript.
Error Types
- Python
- TypeScript
Python uses exception-based error handling with distinct error classes:
| Error Type | Description |
|---|---|
ApiError | Server returned an error response (4xx, 5xx) |
ClientValidationError | Request data failed validation |
AuthenticationError | Authentication failed |
from credoai.errors import ApiError, ClientValidationError
from credoai.auth import AuthenticationError
TypeScript uses a result-based pattern where every API call returns { data, error } instead of throwing exceptions:
| Property | Type | Description |
|---|---|---|
data | T | null | Response data on success |
error | CredoAIError | null | Error object on failure |
error.status | number | HTTP status code |
error.body | unknown | Error response body |
import { createCredoAIClient, CredoAIError, isCredoAIError } from '@credo-ai/sdk';
Handling API Errors
- Python
- TypeScript
from credoai import CredoAI
from credoai.errors import ApiError
client = CredoAI()
try:
use_case = client.use_cases.get(use_case_id="non-existent-id")
except ApiError as e:
print(f"Status code: {e.status_code}")
print(f"Message: {e.message}")
print(f"Details: {e.details}")
import { createCredoAIClient } from '@credo-ai/sdk';
const client = createCredoAIClient('your-tenant');
const { data, error } = await client.useCases.get('non-existent-id');
if (error) {
console.log('Status code:', error.status);
console.log('Details:', error.body);
}
Common Status Codes
| Status Code | Meaning |
|---|---|
| 400 | Bad Request - Invalid request data |
| 401 | Unauthorized - Invalid or missing credentials |
| 403 | Forbidden - Insufficient permissions |
| 404 | Not Found - Resource doesn't exist |
| 409 | Conflict - Resource already exists |
| 422 | Validation Error - Invalid field values |
| 429 | Rate Limited - Too many requests |
| 500 | Server Error - Internal error |
Handling Validation Errors
- Python
- TypeScript
from credoai import CredoAI, UseCaseCreate
from credoai.errors import ClientValidationError
client = CredoAI()
try:
# Missing required field
client.use_cases.create(data=UseCaseCreate())
except ClientValidationError as e:
print(f"Validation failed: {e}")
import { createCredoAIClient } from '@credo-ai/sdk';
const client = createCredoAIClient('your-tenant');
// TypeScript catches type errors at compile time
// Runtime validation errors come back as error responses
const { data, error } = await client.useCases.create({ name: '' });
if (error && error.status === 422) {
console.log('Validation failed:', error.body);
}
Handling Authentication Errors
- Python
- TypeScript
from credoai import CredoAI
from credoai.auth import AuthenticationError
try:
client = CredoAI(api_key="invalid-key")
client.system.ping()
except AuthenticationError as e:
print(f"Authentication failed: {e}")
import { createCredoAIClient } from '@credo-ai/sdk';
const client = createCredoAIClient('your-tenant', {
apiKey: 'invalid-key',
});
const { data, error } = await client.system.ping();
if (error && error.status === 401) {
console.error('Authentication failed:', error.body);
}
Comprehensive Error Handling
- Python
- TypeScript
from credoai import CredoAI, UseCaseCreate
from credoai.errors import ApiError, ClientValidationError
from credoai.auth import AuthenticationError
def create_use_case(name: str, description: str):
client = CredoAI()
try:
use_case = client.use_cases.create(
data=UseCaseCreate(name=name, description=description)
)
return use_case
except ClientValidationError as e:
print(f"Invalid data: {e}")
return None
except AuthenticationError as e:
print(f"Auth failed: {e}")
return None
except ApiError as e:
if e.status_code == 409:
print(f"Use case already exists: {name}")
elif e.status_code == 429:
print("Rate limited - try again later")
else:
print(f"API error ({e.status_code}): {e.message}")
return None
import { createCredoAIClient } from '@credo-ai/sdk';
async function createUseCase(name: string, description: string) {
const client = createCredoAIClient('your-tenant');
const { data, error } = await client.useCases.create({
name,
description,
});
if (error) {
switch (error.status) {
case 401:
console.error('Auth failed:', error.body);
return null;
case 409:
console.error(`Use case already exists: ${name}`);
return null;
case 422:
console.error('Invalid data:', error.body);
return null;
case 429:
console.error('Rate limited - try again later');
return null;
default:
console.error(`API error (${error.status}):`, error.body);
return null;
}
}
return data;
}
Retry Logic
Implement retry logic for transient failures:
- Python
- TypeScript
import time
from credoai import CredoAI
from credoai.errors import ApiError
def with_retry(func, max_retries=3, delay=1.0):
"""Execute a function with retry logic for transient failures."""
for attempt in range(max_retries):
try:
return func()
except ApiError as e:
if e.status_code == 429:
# Rate limited - wait and retry
wait_time = delay * (2 ** attempt)
print(f"Rate limited, waiting {wait_time}s...")
time.sleep(wait_time)
elif e.status_code >= 500:
# Server error - retry
wait_time = delay * (2 ** attempt)
print(f"Server error, retrying in {wait_time}s...")
time.sleep(wait_time)
else:
# Client error - don't retry
raise
raise Exception(f"Failed after {max_retries} attempts")
# Usage
client = CredoAI()
use_case = with_retry(lambda: client.use_cases.get(use_case_id="uc_abc123"))
import { createCredoAIClient, CredoAIError } from '@credo-ai/sdk';
async function withRetry<T>(
fn: () => Promise<{ data: T | null; error: CredoAIError | null }>,
maxRetries = 3,
delay = 1000,
): Promise<T> {
for (let attempt = 0; attempt < maxRetries; attempt++) {
const { data, error } = await fn();
if (!error) return data!;
if (error.status === 429 || error.status >= 500) {
const waitTime = delay * 2 ** attempt;
console.log(`Retrying in ${waitTime}ms...`);
await new Promise((r) => setTimeout(r, waitTime));
} else {
throw error;
}
}
throw new Error(`Failed after ${maxRetries} attempts`);
}
// Usage
const client = createCredoAIClient('your-tenant');
const useCase = await withRetry(() => client.useCases.get('uc_abc123'));
Async Error Handling
- Python
- TypeScript
import asyncio
from credoai import AsyncCredoAI
from credoai.errors import ApiError
async def main():
async with AsyncCredoAI() as client:
try:
use_case = await client.use_cases.get(use_case_id="uc_abc123")
except ApiError as e:
print(f"Error: {e.status_code} - {e.message}")
asyncio.run(main())
// TypeScript is async by default — same pattern as above
const client = createCredoAIClient('your-tenant');
const { data, error } = await client.useCases.get('uc_abc123');
if (error) {
console.error(`Error: ${error.status}`, error.body);
}
Logging Errors
- Python
- TypeScript
import logging
from credoai import CredoAI
from credoai.errors import ApiError
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
client = CredoAI()
try:
response = client.use_cases.list()
except ApiError as e:
logger.error(
"API request failed",
extra={
"status_code": e.status_code,
"message": e.message,
"details": e.details
}
)
raise
import { createCredoAIClient } from '@credo-ai/sdk';
const client = createCredoAIClient('your-tenant');
const { data, error } = await client.useCases.list();
if (error) {
console.error('API request failed', {
statusCode: error.status,
details: error.body,
});
throw error;
}
Next Steps
- Learn about Async Operations
- See the API Reference for endpoint-specific errors