Get Started

Errors

Every Theazo API error uses the same JSON shape and maps to a standard HTTP status. In the SDK, failures throw a typed TheazoError you can branch on by code — no string-parsing of messages.

Response shape

Errors always come back under a top-level error object. details carries structured context specific to the code, and every error includes a requestId (also returned in the X-Request-Id response header).

json
{
  "error": {
    "code": "session_limit_exceeded",
    "message": "Session ses_abc has reached its maxAgents limit (3/3)",
    "details": {
      "sessionId": "ses_abc",
      "limit": 3,
      "current": 3
    },
    "requestId": "req_xyz123"
  }
}

Handling errors in the SDK

Catch TheazoError and read its fields: code, status, message, details, and requestId.

handle-error.ts
try {
  const session = await theazo.sessions.forUser('user_123')
  const agent = await session.agents.create({ compute: 'python' })
  await agent.run('analyze the latest data')
} catch (err) {
  if (err instanceof TheazoError) {
    console.log(err.code)      // a string, e.g. 'session_limit_exceeded'
    console.log(err.status)    // HTTP status, e.g. 429
    console.log(err.message)   // human-readable explanation
    console.log(err.details)   // structured context, e.g. { sessionId, limit, current }
    console.log(err.requestId) // 'req_...' — include this when you contact support
  }
  throw err
}

Standard error codes

These codes are returned across the whole API. Individual endpoints may also return more specific codes (validation like invalid_cron or file_too_large, billing like no_subscription, MCP like mcp_name_conflict). Always branch on err.code as a string and keep a default case rather than assuming the set is closed.

CodeHTTPDescription
invalid_request400Missing or invalid parameters in the request body or query.
unauthorized401Missing or invalid API key.
forbidden403The API key is valid but lacks the required scope or environment.
not_found404The requested resource does not exist.
conflict409Resource state conflict — e.g. the agent is already running.
budget_exhausted402The organization's credit balance or budget is spent.
rate_limited429Too many requests. Back off and retry after the Retry-After window.
session_limit_exceeded429A session limit was hit (maxAgents, maxCost, …). Retrying won't help.
internal_error500An unexpected server error. Safe to retry with backoff.
provider_error502An upstream compute or model provider returned an error.
no_providers_available503All eligible providers are currently unhealthy.

Retrying

Retry transient failures with exponential backoff: rate_limited, timeout, provider_error, no_providers_available, and internal_error. Do not retry errors that won't change on their own — invalid_request, unauthorized, forbidden, not_found, conflict, session_limit_exceeded, and budget_exhausted. Fix the request or the account instead.

retry.ts
// Retry only transient failures, with exponential backoff.
const RETRIABLE = new Set([
  'rate_limited', 'timeout', 'provider_error', 'no_providers_available', 'internal_error',
])

async function withRetry<T>(fn: () => Promise<T>, tries = 3): Promise<T> {
  for (let attempt = 1; ; attempt++) {
    try {
      return await fn()
    } catch (err) {
      const retriable = err instanceof TheazoError && RETRIABLE.has(err.code)
      if (!retriable || attempt >= tries) throw err
      await new Promise((r) => setTimeout(r, 2 ** attempt * 250)) // 500ms, 1s, 2s…
    }
  }
}

const result = await withRetry(() => agent.run('summarize the quarterly report'))
console.log(result.output)
Include the requestId from a failed call when you contact support — it lets us find the exact request in our logs immediately. The SDK also surfaces client-side failures as TheazoError with code connection_error or timeout when a request never reaches the API.
Was this page helpful?