Skip to main content

Error Types

The SDK throws specific errors for different conditions:
import Limitry from '@limitry/sdk';
import {
  LimitryError,          // Base error class
  AuthenticationError,   // 401 - Invalid API key
  RateLimitError,        // 429 - Rate limit exceeded
  NotFoundError,         // 404 - Resource not found
  BadRequestError,       // 400 - Invalid request
  APIError               // Other API errors
} from '@limitry/sdk';

Basic Error Handling

import Limitry from '@limitry/sdk';
import { LimitryError, AuthenticationError, RateLimitError } from '@limitry/sdk';

const client = new Limitry();

try {
  const check = await client.limits.check({ customerId: 'cust_123' });
} catch (error) {
  if (error instanceof AuthenticationError) {
    console.error(`Invalid API key: ${error.message}`);
  } else if (error instanceof RateLimitError) {
    console.error(`Rate limited. Retry after ${error.retryAfter} seconds`);
  } else if (error instanceof LimitryError) {
    console.error(`API error: ${error.message}`);
  } else {
    throw error;
  }
}

Authentication Errors

Thrown when the API key is invalid or missing:
import { AuthenticationError } from '@limitry/sdk';

try {
  const client = new Limitry({ apiKey: 'invalid_key' });
  await client.project.retrieve();
} catch (error) {
  if (error instanceof AuthenticationError) {
    console.error(`Authentication failed: ${error.message}`);
    console.error(`Status code: ${error.status}`);  // 401
  }
}

Rate Limit Errors

Thrown when you hit Limitry’s own API rate limits:
import { RateLimitError } from '@limitry/sdk';

try {
  const check = await client.limits.check({ customerId: 'cust_123' });
} catch (error) {
  if (error instanceof RateLimitError) {
    console.error(`Rate limited: ${error.message}`);
    console.error(`Retry after: ${error.retryAfter} seconds`);
    
    // Wait and retry
    await new Promise(resolve => setTimeout(resolve, error.retryAfter * 1000));
    const check = await client.limits.check({ customerId: 'cust_123' });
  }
}

Handling Usage Check Responses

When a customer exceeds their limits, the check returns allowed: false (not an error):
const check = await client.limits.check({ customerId: 'cust_123' });

if (!check.allowed) {
  // This is NOT an error - it's expected behavior
  console.log(`Customer blocked: ${check.error}`);
  
  // Check which limits were exceeded
  for (const limit of check.limits) {
    if (limit.exceeded) {
      console.log(`Limit exceeded: ${limit.name}`);
      console.log(`Used ${limit.currentValue}/${limit.value}`);
    }
  }
}

Not Found Errors

Thrown when a resource doesn’t exist:
import { NotFoundError } from '@limitry/sdk';

try {
  const limit = await client.limits.retrieve('lmt_nonexistent');
} catch (error) {
  if (error instanceof NotFoundError) {
    console.error(`Limit not found: ${error.message}`);
  }
}

Bad Request Errors

Thrown when the request is malformed:
import { BadRequestError } from '@limitry/sdk';

try {
  // Invalid period value
  const limit = await client.limits.create({
    name: 'Invalid limit',
    meterId: 'mtr_123',
    value: 100,
    period: 'invalid_period' as any
  });
} catch (error) {
  if (error instanceof BadRequestError) {
    console.error(`Invalid request: ${error.message}`);
  }
}

Full Example

import Limitry from '@limitry/sdk';
import {
  AuthenticationError,
  RateLimitError,
  NotFoundError,
  BadRequestError,
  LimitryError
} from '@limitry/sdk';

async function safeCheckLimits(
  client: Limitry,
  customerId: string,
  retries = 3
): Promise<{ allowed: boolean; error?: string }> {
  
  for (let attempt = 0; attempt < retries; attempt++) {
    try {
      const check = await client.limits.check({ customerId });
      
      if (!check.allowed) {
        return { allowed: false, error: check.error };
      }
      
      return { allowed: true };
      
    } catch (error) {
      if (error instanceof RateLimitError) {
        if (attempt < retries - 1) {
          await new Promise(r => setTimeout(r, (error.retryAfter || 1) * 1000));
          continue;
        }
        throw error;
      }
      
      if (error instanceof AuthenticationError) {
        throw error;  // Don't retry auth errors
      }
      
      if (error instanceof LimitryError) {
        if (attempt < retries - 1) {
          await new Promise(r => setTimeout(r, Math.pow(2, attempt) * 1000));
          continue;
        }
        throw error;
      }
      
      throw error;
    }
  }
  
  throw new Error('Max retries exceeded');
}

// Usage
const client = new Limitry();

try {
  const result = await safeCheckLimits(client, 'cust_123');
  
  if (!result.allowed) {
    console.log(`Customer blocked: ${result.error}`);
  } else {
    console.log('Proceeding with API call...');
  }
  
} catch (error) {
  if (error instanceof AuthenticationError) {
    console.error('Check your API key');
  } else if (error instanceof LimitryError) {
    console.error(`Limitry error: ${error.message}`);
  }
}