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¶
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:
The server returns HTTP 401
You call a protected endpoint without an API key (raised locally, no request made)
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.
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:
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:
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_rangeset withoutsorting=Sort.TOPLISTInvalid resolution format (e.g.,
"1920-1080"instead of"1920x1080")Invalid ratio format
Invalid seed length or characters
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.):
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:
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())