Skip to main content
The Avala SDK provides comprehensive error handling with specific error types for different failure scenarios. All errors extend the base AvalaError class and include helpful context.

Error types

The SDK throws specific error types based on the response status code:
import { AvalaError } from '@avala-ai/sdk';

try {
  const dataset = await avala.datasets.get('dataset-uid');
} catch (error) {
  if (error instanceof AvalaError) {
    console.error('Status:', error.statusCode);
    console.error('Message:', error.message);
    console.error('Body:', error.body);
  }
}

All error classes

The SDK includes these error types:
Error classStatus codeDescription
AvalaErrorAnyBase error class for all SDK errors
AuthenticationError401Invalid or missing API key
NotFoundError404Requested resource does not exist
RateLimitError429Rate limit exceeded
ValidationError400, 422Invalid request parameters
ServerError5xxServer-side error

Handling validation errors

Validation errors include detailed information about what went wrong:
import { ValidationError } from '@avala-ai/sdk';

try {
  const dataset = await avala.datasets.create({
    name: '', // Invalid: empty name
    slug: 'my-dataset'
  });
} catch (error) {
  if (error instanceof ValidationError) {
    console.error('Validation failed:', error.message);
    console.error('Status:', error.statusCode); // 400 or 422
    console.error('Details:', error.details);
    console.error('Response:', error.body);
  }
}
Validation errors contain a details array with field-level error information when available.

Handling rate limits

Rate limit errors include retry timing information:
1

Catch rate limit errors

Use the RateLimitError class to detect when you’ve exceeded rate limits:
import { RateLimitError } from '@avala-ai/sdk';

try {
  const datasets = await avala.datasets.list();
} catch (error) {
  if (error instanceof RateLimitError) {
    console.error('Rate limit exceeded');
    console.error('Retry after:', error.retryAfter, 'seconds');
  }
}
2

Implement retry logic

Use the retryAfter property to determine when to retry:
async function withRetry<T>(fn: () => Promise<T>): Promise<T> {
  try {
    return await fn();
  } catch (error) {
    if (error instanceof RateLimitError && error.retryAfter) {
      await new Promise(resolve => 
        setTimeout(resolve, error.retryAfter * 1000)
      );
      return await fn();
    }
    throw error;
  }
}

const datasets = await withRetry(() => avala.datasets.list());
3

Check rate limit status

Monitor your rate limit status proactively:
const datasets = await avala.datasets.list();

const rateLimit = avala.rateLimitInfo;
console.log('Limit:', rateLimit.limit);
console.log('Remaining:', rateLimit.remaining);
console.log('Reset:', rateLimit.reset);
The retryAfter property may be null if the server doesn’t provide a Retry-After header. Always check for null before using it.

Error response body

All errors include the raw response body for debugging:
try {
  const export = await avala.exports.create({
    datasetUid: 'dataset-uid',
    format: 'invalid-format'
  });
} catch (error) {
  if (error instanceof AvalaError) {
    // Access the raw API response
    console.error('Raw response:', error.body);
    
    // The body may contain additional error details
    // from the API that aren't in the message
  }
}

Best practices

1

Check specific error types first

Always check for specific error types before the base AvalaError:
try {
  const dataset = await avala.datasets.get('dataset-uid');
} catch (error) {
  if (error instanceof RateLimitError) {
    // Handle rate limiting
  } else if (error instanceof AuthenticationError) {
    // Handle authentication
  } else if (error instanceof NotFoundError) {
    // Handle not found
  } else if (error instanceof ValidationError) {
    // Handle validation errors
  } else if (error instanceof AvalaError) {
    // Handle other API errors
  } else {
    // Handle non-API errors
    throw error;
  }
}
2

Log error context for debugging

Include status codes and response bodies in logs:
try {
  const result = await avala.projects.create({
    name: 'My Project'
  });
} catch (error) {
  if (error instanceof AvalaError) {
    console.error({
      message: error.message,
      statusCode: error.statusCode,
      body: error.body,
      stack: error.stack
    });
  }
}
3

Provide user-friendly messages

Don’t expose raw error messages to end users:
async function createDataset(name: string) {
  try {
    return await avala.datasets.create({ name });
  } catch (error) {
    if (error instanceof AuthenticationError) {
      throw new Error('Authentication failed. Please check your API key.');
    } else if (error instanceof ValidationError) {
      throw new Error(`Invalid dataset name: ${error.message}`);
    } else {
      throw new Error('Failed to create dataset. Please try again.');
    }
  }
}
Use TypeScript’s instanceof checks to get full type safety when handling errors.

Server errors

Server errors (5xx status codes) are thrown as ServerError:
import { ServerError } from '@avala-ai/sdk';

try {
  const datasets = await avala.datasets.list();
} catch (error) {
  if (error instanceof ServerError) {
    console.error('Server error:', error.statusCode);
    console.error('Message:', error.message);
    
    // Implement exponential backoff retry
    // for server errors
  }
}
For server errors, implement exponential backoff retry logic rather than immediately retrying.

Build docs developers (and LLMs) love