Error Handling

Updated

The SDK exposes two error classes for structured error handling:

ClassPropertiesWhen Thrown
ChaosErrormessage, status?, code?, type?HTTP errors, connection failures, stream errors, aborted requests
ChaosTimeoutErrormessage (includes timeout duration)Request exceeds the configured timeout

ChaosTimeoutError extends ChaosError, so a single catch (e) { if (e instanceof ChaosError) } block catches both.

Basic Try/Catch

error-basic.ts
import { Chaos, WALLET_MODEL, ChaosError, ChaosTimeoutError } 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: 'Show my portfolio' },
    ],
    metadata: {
      user_id: 'user-1',
      session_id: 'session-1',
      wallets: [{ address: '0xYourWallet', chain: 'ethereum' }],
    },
  });
 
  console.log('Response:', response.status);
} catch (error) {
  if (error instanceof ChaosTimeoutError) {
    // Request took too long
    console.error('Request timed out:', error.message);
  } else if (error instanceof ChaosError) {
    // HTTP or connection error
    console.error('API error:', error.message);
    if (error.status) console.error('  HTTP status:', error.status);
    if (error.code) console.error('  Error code:', error.code);
    if (error.type) console.error('  Error type:', error.type);
  } else {
    // Unexpected error
    console.error('Unexpected error:', error);
  }
}
[@portabletext/react] Unknown block type "callout", specify a component for it in the `components.types` prop

Timeout Configuration

The default timeout is 120 seconds (120000ms). Override it per-client.

error-timeout-config.ts
import { Chaos } from '@chaoslabs/ai-sdk';
 
// Short timeout for quick queries
const fastClient = new Chaos({
  apiKey: process.env.CHAOS_API_KEY!,
  timeout: 30_000, // 30 seconds
});
 
// Long timeout for complex portfolio analysis
const slowClient = new Chaos({
  apiKey: process.env.CHAOS_API_KEY!,
  timeout: 300_000, // 5 minutes
});

Retry with Exponential Backoff

Wrap requests in a retry helper for transient failures.

error-retry.ts
import {
  Chaos,
  WALLET_MODEL,
  ChaosError,
  ChaosTimeoutError,
} from '@chaoslabs/ai-sdk';
import type { ChatCreateRequestParams, ChatCreateResponse } from '@chaoslabs/ai-sdk';
 
interface RetryOptions {
  maxRetries: number;
  baseDelayMs: number;
  maxDelayMs: number;
}
 
const DEFAULT_RETRY: RetryOptions = {
  maxRetries: 3,
  baseDelayMs: 1000,
  maxDelayMs: 30_000,
};
 
async function withRetry(
  chaos: Chaos,
  params: ChatCreateRequestParams,
  options: RetryOptions = DEFAULT_RETRY
): Promise<ChatCreateResponse> {
  let lastError: Error | undefined;
 
  for (let attempt = 0; attempt <= options.maxRetries; attempt++) {
    try {
      return await chaos.chat.responses.create(params);
    } catch (error) {
      lastError = error instanceof Error ? error : new Error(String(error));
 
      // Don't retry client errors (4xx)
      if (error instanceof ChaosError && error.status && error.status < 500) {
        throw error;
      }
 
      if (attempt < options.maxRetries) {
        const delay = Math.min(
          options.baseDelayMs * Math.pow(2, attempt),
          options.maxDelayMs
        );
        // Add jitter: +/- 25%
        const jitter = delay * 0.25 * (Math.random() * 2 - 1);
        const waitMs = Math.round(delay + jitter);
 
        console.log(
          `Attempt ${attempt + 1} failed: ${lastError.message}. ` +
          `Retrying in ${waitMs}ms...`
        );
        await new Promise((resolve) => setTimeout(resolve, waitMs));
      }
    }
  }
 
  throw lastError;
}
 
// Usage
const chaos = new Chaos({ apiKey: process.env.CHAOS_API_KEY! });
 
const response = await withRetry(chaos, {
  model: WALLET_MODEL,
  input: [
    { type: 'message', role: 'user', content: 'Show my portfolio' },
  ],
  metadata: {
    user_id: 'user-1',
    session_id: 'session-1',
    wallets: [{ address: '0xYourWallet', chain: 'ethereum' }],
  },
});
 
console.log(`Success after retries. Status: ${response.status}`);

Handling Response-Level Errors

The response itself can indicate failure via status: "failed" and an optional error object, even when no exception is thrown.

error-response-level.ts
import { Chaos, WALLET_MODEL } from '@chaoslabs/ai-sdk';
 
const chaos = new Chaos({ apiKey: process.env.CHAOS_API_KEY! });
 
const response = await chaos.chat.responses.create({
  model: WALLET_MODEL,
  input: [
    { type: 'message', role: 'user', content: 'Show my portfolio' },
  ],
  metadata: {
    user_id: 'user-1',
    session_id: 'session-1',
    wallets: [{ address: '0xYourWallet', chain: 'ethereum' }],
  },
});
 
if (response.status === 'failed') {
  console.error('Response failed.');
  if (response.error) {
    console.error('  Message:', response.error.message);
    console.error('  Type:', response.error.type);
    console.error('  Code:', response.error.code);
  }
} else {
  console.log('Success. Messages:', response.messages?.length ?? 0);
}

Cancellation

Abort an in-flight request. The SDK throws a ChaosError with message "Request aborted".

error-cancellation.ts
import { Chaos, WALLET_MODEL, ChaosError } from '@chaoslabs/ai-sdk';
 
const chaos = new Chaos({ apiKey: process.env.CHAOS_API_KEY! });
 
// Cancel after 10 seconds
const timer = setTimeout(() => {
  console.log('Cancelling request...');
  chaos.chat.responses.cancel();
}, 10_000);
 
try {
  const response = await chaos.chat.responses.create({
    model: WALLET_MODEL,
    input: [
      { type: 'message', role: 'user', content: 'Detailed portfolio analysis' },
    ],
    metadata: {
      user_id: 'user-1',
      session_id: 'session-1',
      wallets: [{ address: '0xYourWallet', chain: 'ethereum' }],
    },
  });
  clearTimeout(timer);
  console.log('Completed:', response.status);
} catch (error) {
  clearTimeout(timer);
  if (error instanceof ChaosError && error.message === 'Request aborted') {
    console.log('Request was cancelled by the user.');
  } else {
    throw error;
  }
}
[@portabletext/react] Unknown block type "callout", specify a component for it in the `components.types` prop
Was this helpful?