Error Handling

Updated

The SDK provides two error classes that extend the built-in Error class. All API errors and timeout conditions are surfaced through these types, making error handling predictable with instanceof checks.

import.ts
import { ChaosError, ChaosTimeoutError } from '@chaoslabs/ai-sdk';

ChaosError

The base error class for all SDK errors. Extends the native Error class with optional HTTP metadata.

chaos-error.ts
export class ChaosError extends Error {
  constructor(
    message: string,
    public readonly status?: number,
    public readonly code?: string,
    public readonly type?: string
  ) {
    super(message);
    this.name = 'ChaosError';
  }
}

Properties

PropertyTypeDescription
messagestringHuman-readable error description (inherited from Error)
namestringAlways 'ChaosError'
statusnumber | undefinedHTTP status code (e.g., 401, 429, 500)
codestring | undefinedMachine-readable error code from the API
typestring | undefinedError type classification from the API

ChaosError is thrown for:

  • HTTP errors (4xx, 5xx status codes)
  • Connection errors
  • Stream errors (unexpected close, read failures)
  • Aborted requests

ChaosTimeoutError

Thrown when a request exceeds the configured timeout. Extends ChaosError.

chaos-timeout-error.ts
export class ChaosTimeoutError extends ChaosError {
  constructor(timeoutMs: number) {
    super(`Request timed out after ${timeoutMs}ms`);
    this.name = 'ChaosTimeoutError';
  }
}

The timeout is configured via the timeout option when initializing the client (default: 120000ms / 2 minutes). The timer resets on each data chunk received during streaming, so the timeout applies to periods of inactivity rather than total request duration.

[@portabletext/react] Unknown block type "callout", specify a component for it in the `components.types` prop

Error Handling Patterns

Basic try/catch

basic-error-handling.ts
import { Chaos, ChaosError, ChaosTimeoutError, WALLET_MODEL } from '@chaoslabs/ai-sdk';
 
const chaos = new Chaos({ apiKey: process.env.CHAOS_API_KEY! });
 
try {
  const response = await chaos.chat.responses.create({
    model: WALLET_MODEL,
    input: [{ type: 'message', role: 'user', content: 'Swap 1 ETH to USDC' }],
    metadata: {
      user_id: 'user-123',
      session_id: 'session-456',
      wallets: [{ address: '0x...', chain: 'ethereum' }],
    },
  });
  console.log('Success:', response.status);
} catch (error) {
  if (error instanceof ChaosTimeoutError) {
    console.error('Request timed out — consider increasing the timeout');
  } else if (error instanceof ChaosError) {
    console.error(`API error: ${error.message}`);
    if (error.status === 401) {
      console.error('Invalid API key');
    } else if (error.status === 429) {
      console.error('Rate limited — retry after backoff');
    }
  } else {
    throw error; // Re-throw unexpected errors
  }
}

Checking Error Order

Since ChaosTimeoutError extends ChaosError, always check for the more specific type first.

error-order.ts
try {
  await chaos.chat.responses.create(params);
} catch (error) {
  // Check ChaosTimeoutError BEFORE ChaosError
  if (error instanceof ChaosTimeoutError) {
    // Timeout-specific handling
  } else if (error instanceof ChaosError) {
    // General API error handling
  }
}
[@portabletext/react] Unknown block type "callout", specify a component for it in the `components.types` prop

Retry Pattern

retry-pattern.ts
import { Chaos, ChaosError, ChaosTimeoutError, WALLET_MODEL } from '@chaoslabs/ai-sdk';
import type { ChatCreateRequestParams } from '@chaoslabs/ai-sdk';
 
async function withRetry(
  chaos: Chaos,
  params: ChatCreateRequestParams,
  maxRetries = 3
) {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      return await chaos.chat.responses.create(params);
    } catch (error) {
      if (error instanceof ChaosTimeoutError && attempt < maxRetries) {
        console.log(`Attempt ${attempt} timed out, retrying...`);
        continue;
      }
      if (
        error instanceof ChaosError &&
        error.status === 429 &&
        attempt < maxRetries
      ) {
        const delay = Math.pow(2, attempt) * 1000;
        console.log(`Rate limited, retrying in ${delay}ms...`);
        await new Promise((r) => setTimeout(r, delay));
        continue;
      }
      throw error;
    }
  }
  throw new ChaosError('Max retries exceeded');
}

Helper Functions

The SDK also provides helper functions on ChatCreateResponse for common safety checks.

hasRisks

Returns true if any transaction action block has a risk level above 'low'.

has-risks.ts
export function hasRisks(response: ChatCreateResponse): boolean;
 
// Usage
if (hasRisks(response)) {
  console.log('This response contains elevated risk levels');
}

hasBlockers

Returns true if any transaction action block has 'high' or 'critical' risk level, or contains any blocker items.

has-blockers.ts
export function hasBlockers(response: ChatCreateResponse): boolean;
 
// Usage
if (hasBlockers(response)) {
  console.log('Transaction blocked — do not proceed');
}
Was this helpful?