Skip to content

Error Handling

Both SDKs provide typed exception/error classes that map directly to API error codes.

Error Response Format

All API errors return:

{
  "error": {
    "code": "ERROR_CODE",
    "message": "Human-readable description.",
    "status": 401,
    "details": {},
    "request_id": "req_abc123",
    "timestamp": "2026-02-19T12:00:00Z"
  }
}

Python

from cloman import CloMan, CloManError
from cloman._exceptions import (
    AuthenticationError,
    AuthorizationError,
    NotFoundError,
    ValidationError,
    RateLimitError,
    ServerError,
    TimeoutError,
)

client = CloMan(api_key="cloman_...")

try:
    result = client.decide(context="Should we approve?")
except AuthenticationError as e:
    # 401 — Invalid or expired API key
    print(f"Auth failed: {e.message}")

except AuthorizationError as e:
    # 403 — Key lacks required permissions
    print(f"Not authorized: {e.message}")

except NotFoundError as e:
    # 404 — Clone not found
    print(f"Not found: {e.message}")

except ValidationError as e:
    # 422 — Invalid request data
    print(f"Validation error: {e.message}")
    print(f"Details: {e.details}")

except RateLimitError as e:
    # 429 — Rate limit exceeded
    print(f"Rate limited: {e.message}")
    if e.retry_after:
        print(f"Retry after {e.retry_after}s")

except TimeoutError as e:
    # Request timed out
    print(f"Timeout: {e.message}")

except ServerError as e:
    # 5xx — Server error (retries were exhausted)
    print(f"Server error: {e.message}")

except CloManError as e:
    # Catch-all for any other API error
    print(f"[{e.code}] {e.message}")

TypeScript

import {
  CloMan,
  CloManError,
  AuthenticationError,
  AuthorizationError,
  NotFoundError,
  ValidationError,
  RateLimitError,
  ServerError,
  TimeoutError,
} from "@clomanai/sdk";

const client = new CloMan("cloman_...");

try {
  const result = await client.decide({ context: "Should we approve?" });
} catch (error) {
  if (error instanceof AuthenticationError) {
    // 401
    console.error("Auth failed:", error.message);
  } else if (error instanceof AuthorizationError) {
    // 403
    console.error("Not authorized:", error.message);
  } else if (error instanceof NotFoundError) {
    // 404
    console.error("Not found:", error.message);
  } else if (error instanceof ValidationError) {
    // 422
    console.error("Validation error:", error.message);
  } else if (error instanceof RateLimitError) {
    // 429
    console.error("Rate limited:", error.message);
    if (error.retryAfter) {
      console.error(`Retry after ${error.retryAfter}s`);
    }
  } else if (error instanceof TimeoutError) {
    console.error("Timeout:", error.message);
  } else if (error instanceof ServerError) {
    // 5xx
    console.error("Server error:", error.message);
  } else if (error instanceof CloManError) {
    // Catch-all
    console.error(`[${error.code}]`, error.message);
  } else {
    throw error; // Non-API error
  }
}

Best Practices

  1. Catch specific errors first, then use CloManError as a catch-all.
  2. Always handle RateLimitError — it's the most common recoverable error.
  3. Log the request_id — it helps CloMan support debug issues.
  4. Don't retry 4xx errors — they indicate a client-side problem that won't resolve by retrying.
  5. Let the SDK retry 5xx — both SDKs retry server errors automatically with exponential backoff.