Skip to main content

Error Types

The SDK raises specific exceptions for different error conditions:
from limitry import Limitry
from limitry.errors import (
    LimitryError,          # Base exception
    AuthenticationError,   # 401 - Invalid API key
    RateLimitError,        # 429 - Rate limit exceeded
    NotFoundError,         # 404 - Resource not found
    BadRequestError,       # 400 - Invalid request
    APIError               # Other API errors
)

Basic Error Handling

from limitry import Limitry
from limitry.errors import LimitryError, AuthenticationError, RateLimitError

client = Limitry()

try:
    check = client.limits.check(customer_id="cust_123")
except AuthenticationError as e:
    print(f"Invalid API key: {e}")
except RateLimitError as e:
    print(f"Rate limited. Retry after {e.retry_after} seconds")
except LimitryError as e:
    print(f"API error: {e}")

Authentication Errors

Raised when the API key is invalid or missing:
from limitry.errors import AuthenticationError

try:
    client = Limitry(api_key="invalid_key")
    client.project.retrieve()
except AuthenticationError as e:
    print(f"Authentication failed: {e}")
    print(f"Status code: {e.status_code}")  # 401

Rate Limit Errors

Raised when you hit Limitry’s own API rate limits:
from limitry.errors import RateLimitError
import time

try:
    check = client.limits.check(customer_id="cust_123")
except RateLimitError as e:
    print(f"Rate limited: {e}")
    print(f"Retry after: {e.retry_after} seconds")
    
    # Wait and retry
    time.sleep(e.retry_after)
    check = client.limits.check(customer_id="cust_123")

Handling Usage Check Responses

When a customer exceeds their limits, the check returns allowed=False (not an exception):
check = client.limits.check(customer_id="cust_123")

if not check.allowed:
    # This is NOT an exception - it's expected behavior
    print(f"Customer blocked: {check.error}")
    
    # Check which limits were exceeded
    for limit in check.limits:
        if limit.exceeded:
            print(f"Limit exceeded: {limit.name}")
            print(f"Used {limit.current_value}/{limit.value}")

Not Found Errors

Raised when a resource doesn’t exist:
from limitry.errors import NotFoundError

try:
    limit = client.limits.retrieve("lmt_nonexistent")
except NotFoundError as e:
    print(f"Limit not found: {e}")

Bad Request Errors

Raised when the request is malformed:
from limitry.errors import BadRequestError

try:
    # Invalid period value
    limit = client.limits.create(
        name="Invalid limit",
        meter_id="mtr_123",
        value=100,
        period="invalid_period"
    )
except BadRequestError as e:
    print(f"Invalid request: {e}")

Full Example

from limitry import Limitry
from limitry.errors import (
    AuthenticationError,
    RateLimitError,
    NotFoundError,
    BadRequestError,
    LimitryError
)
import time

def safe_check_limits(client: Limitry, customer_id: str, retries: int = 3):
    """Check limits with retry logic and error handling."""
    
    for attempt in range(retries):
        try:
            check = client.limits.check(customer_id=customer_id)
            
            if not check.allowed:
                return None, check.error
            
            return check, None
            
        except RateLimitError as e:
            if attempt < retries - 1:
                time.sleep(e.retry_after or 1)
                continue
            raise
            
        except AuthenticationError:
            raise  # Don't retry auth errors
            
        except LimitryError as e:
            if attempt < retries - 1:
                time.sleep(2 ** attempt)  # Exponential backoff
                continue
            raise

# Usage
client = Limitry()

try:
    check, error = safe_check_limits(client, "cust_123")
    
    if error:
        print(f"Customer blocked: {error}")
    else:
        print("Proceeding with API call...")
        
except AuthenticationError:
    print("Check your API key")
except LimitryError as e:
    print(f"Limitry error: {e}")