Skip to main content

Overview

The Avaliar SDK provides a structured error hierarchy so you can catch and handle specific failure modes. Transient errors are retried automatically with exponential backoff, while permanent errors are raised immediately.

Error Hierarchy

All SDK errors inherit from AvaliarError. Catch this base class to handle any Avaliar-related failure, or catch specific subclasses for fine-grained control.
AvaliarError
├── AvaliarAPIError          # Server errors (HTTP 500, 503)
├── AvaliarRequestTimeout    # Request timed out
├── AvaliarUserError         # Invalid input or configuration
├── AvaliarRateLimitError    # Rate limit exceeded (HTTP 429)
├── AvaliarAuthError         # Authentication failed (HTTP 401)
├── AvaliarNotFoundError     # Resource not found (HTTP 404)
├── AvaliarConflictError     # Resource conflict (HTTP 409)
├── AvaliarConnectionError   # Network connectivity issues
└── PromptBlockedError       # Prompt blocked by safety check (blocking mode)

PromptBlockedError

Raised when blocking mode is enabled and a prompt is flagged before reaching the LLM:
from avaliar import traceable, PromptBlockedError

@traceable("llm", model="gpt-4o", provider="openai", blocking=True)
async def generate(messages: list) -> str:
    ...

try:
    result = await generate(messages)
except PromptBlockedError as e:
    print(e.reason)   # Why the prompt was blocked
    print(e.issues)   # List of detected issues (may be None)
    # Return a safe fallback response

Error Reference

Error ClassHTTP StatusDescriptionRetried?
AvaliarAPIError500, 503Server-side errorYes
AvaliarRequestTimeoutRequest exceeded timeoutNo
AvaliarUserError400, 422Invalid input or configurationNo
AvaliarRateLimitError429Too many requestsYes
AvaliarAuthError401Invalid or expired API keyNo
AvaliarNotFoundError404Resource does not existNo
AvaliarConflictError409Resource already exists or conflictNo
AvaliarConnectionErrorCould not reach the APIYes

Retry Strategy

The SDK automatically retries transient errors using exponential backoff with jitter. You do not need to implement retry logic yourself.
1

Retryable Errors

The following error types are retried automatically:
  • AvaliarConnectionError — network failures and DNS resolution issues
  • AvaliarAPIError — server errors (HTTP 500, 503)
  • AvaliarRateLimitError — rate limit responses (HTTP 429)
2

Backoff Formula

Each retry waits longer than the previous one:
delay = 2^attempt + random_jitter(0, 0.5)
AttemptWait time
1st retry1.0–1.5s
2nd retry2.0–2.5s
3rd retry4.0–4.5s
3

Max Retries

The SDK retries up to 3 times by default. After all retries are exhausted, the original error is raised.

Catching Errors

Catch a Specific Error

from avaliar.errors.client_errors import AvaliarAuthError, AvaliarRateLimitError

try:
    result = await generate(messages)
except AvaliarAuthError:
    print("Invalid API key. Check your AVALIAR_API_KEY environment variable.")
except AvaliarRateLimitError:
    print("Rate limited. The SDK retried automatically but the limit persists.")

Catch All Avaliar Errors

from avaliar.errors.client_errors import AvaliarError

try:
    result = await generate(messages)
except AvaliarError as e:
    print(f"Avaliar SDK error: {e}")

Handle Errors by Category

from avaliar.errors.client_errors import (
    AvaliarError,
    AvaliarAuthError,
    AvaliarUserError,
    AvaliarRateLimitError,
    AvaliarAPIError,
    AvaliarConnectionError,
    AvaliarNotFoundError,
    AvaliarRequestTimeout,
)

try:
    result = await generate(messages)

except AvaliarAuthError:
    # Permanent: check your API key
    logger.error("Authentication failed. Verify AVALIAR_API_KEY is correct.")

except AvaliarUserError as e:
    # Permanent: fix the request
    logger.error(f"Invalid request: {e}")

except AvaliarNotFoundError:
    # Permanent: the resource does not exist
    logger.error("Requested resource was not found.")

except AvaliarRequestTimeout:
    # Consider increasing the timeout
    logger.warning("Request timed out.")

except (AvaliarAPIError, AvaliarConnectionError, AvaliarRateLimitError) as e:
    # Transient: already retried automatically
    logger.warning(f"Transient error after retries: {e}")

except AvaliarError as e:
    # Catch-all for any other SDK error
    logger.error(f"Unexpected Avaliar error: {e}")

Background error handling

Trace submission happens in background threads. By default, errors in background submission are silently handled — they do not crash your application. If you need to observe or log those failures, use the client directly:
from avaliar.client import Client

client = Client()

def on_error(e: Exception):
    logger.error(f"Trace submission failed: {e}")

client.thread_request_with_retries(
    method="POST",
    data=trace_data,
    on_error=on_error,
)

Configuration

Timeout Settings

Configure request timeouts through the SDK client:
import os

# Set the request timeout in seconds (default: 30)
os.environ["AVALIAR_REQUEST_TIMEOUT"] = "60"
Non-retryable errors such as AvaliarAuthError and AvaliarUserError are raised immediately. Do not retry these — they indicate a problem that requires a code or configuration change.
In production, catch AvaliarError broadly and log the details. Use specific exception handlers only where you need to take different recovery actions for different failure modes.