# Error Handling All xanax exceptions inherit from `XanaxError`. This means you can catch everything with a single `except XanaxError` or be specific about what you handle. ## Exception hierarchy ``` XanaxError ├── AuthenticationError — 401 responses, or missing API key for protected content ├── RateLimitError — 429 responses; has .retry_after ├── NotFoundError — 404 responses ├── ValidationError — invalid parameters (raised before any request) └── APIError — other 4xx/5xx responses; has .status_code ``` ## Full example ```python from xanax import Wallhaven, SearchParams from xanax.errors import ( AuthenticationError, RateLimitError, NotFoundError, ValidationError, APIError, XanaxError, ) client = Wallhaven(api_key="your-api-key") try: results = client.search(SearchParams(query="anime")) except AuthenticationError: print("Invalid or missing API key") except RateLimitError as e: print(f"Rate limited. Retry after {e.retry_after} seconds") except NotFoundError: print("Resource not found") except ValidationError as e: print(f"Invalid parameters: {e}") except APIError as e: print(f"API error {e.status_code}: {e}") except XanaxError as e: print(f"Unexpected xanax error: {e}") ``` ## AuthenticationError Raised in two situations: 1. The server returns HTTP 401 2. You call a protected endpoint without an API key (raised locally, no request made) ```python client = Wallhaven() try: client.settings() # requires API key except AuthenticationError as e: print(e) # "User settings require an API key..." ``` ## RateLimitError Raised when the API returns HTTP 429. The Wallhaven API allows 45 requests per minute. ```python from xanax.errors import RateLimitError try: result = client.search(params) except RateLimitError as e: print(e.retry_after) # seconds to wait (float or None if not provided by API) ``` To avoid handling this yourself, configure automatic retry: ```python client = Wallhaven(max_retries=3) # retry up to 3 times with exponential backoff ``` With `max_retries=3`, the client waits `2^attempt` seconds between retries (1s, 2s, 4s). If all retries are exhausted, `RateLimitError` is raised. ## NotFoundError Raised on HTTP 404. Typically means the wallpaper or tag ID doesn't exist: ```python try: wallpaper = client.wallpaper("doesnotexist") except NotFoundError: print("Wallpaper not found") ``` ## ValidationError Raised locally before any network request when search parameters are invalid. Common causes: - `top_range` set without `sorting=Sort.TOPLIST` - Invalid resolution format (e.g., `"1920-1080"` instead of `"1920x1080"`) - Invalid ratio format - Invalid seed length or characters ```python from xanax.errors import ValidationError try: SearchParams(sorting=Sort.DATE_ADDED, top_range=TopRange.ONE_MONTH) except ValidationError as e: print(e) # "top_range requires sorting=toplist" ``` ## APIError Catch-all for other HTTP errors (500, 503, etc.): ```python from xanax.errors import APIError try: result = client.search(params) except APIError as e: print(e.status_code) # e.g. 503 print(e.message) ``` ## Async error handling The async client raises the same exceptions: ```python import asyncio from xanax import AsyncWallhaven, SearchParams from xanax.errors import RateLimitError async def main(): async with AsyncWallhaven(api_key="your-api-key", max_retries=3) as client: try: result = await client.search(SearchParams(query="anime")) except RateLimitError as e: print(f"Still rate limited after retries: {e.retry_after}s") asyncio.run(main()) ```