Error Handling¶
Headroom provides explicit exceptions for debugging, with a safety guarantee that compression failures never break your LLM calls.
Exception Hierarchy¶
from headroom import (
HeadroomError, # Base class - catch all Headroom errors
ConfigurationError, # Invalid configuration
ProviderError, # Provider issues (unknown model, etc.)
StorageError, # Database/storage failures
CompressionError, # Compression failures (rare)
ValidationError, # Setup validation failures
)
Usage¶
from headroom import (
HeadroomClient,
HeadroomError,
ConfigurationError,
StorageError,
)
try:
client = HeadroomClient(...)
response = client.chat.completions.create(...)
except ConfigurationError as e:
print(f"Config issue: {e}")
print(f"Details: {e.details}") # Additional context
except StorageError as e:
print(f"Storage issue: {e}")
# Headroom continues to work, just without metrics persistence
except HeadroomError as e:
print(f"Headroom error: {e}")
Exception Types¶
ConfigurationError¶
Raised when configuration is invalid.
# Examples:
# - Invalid mode value
# - Missing required provider
# - Invalid model context limit
try:
client = HeadroomClient(
original_client=OpenAI(),
provider=OpenAIProvider(),
default_mode="invalid_mode", # Will raise ConfigurationError
)
except ConfigurationError as e:
print(f"Config error: {e}")
print(f"Field: {e.details.get('field')}")
ProviderError¶
Raised for provider-specific issues.
# Examples:
# - Unknown model name
# - Provider API error
# - Token counting failure
try:
response = client.chat.completions.create(
model="unknown-model-xyz",
messages=[...]
)
except ProviderError as e:
print(f"Provider error: {e}")
print(f"Provider: {e.details.get('provider')}")
StorageError¶
Raised when database operations fail.
# Examples:
# - Database connection failure
# - Write permission denied
# - Disk full
try:
metrics = client.get_metrics()
except StorageError as e:
print(f"Storage error: {e}")
# Application can continue - just won't have metrics
CompressionError¶
Raised when compression fails (rare).
# Examples:
# - Malformed JSON in tool output
# - Unexpected data structure
# Note: In practice, compression errors are caught internally
# and the original content passes through unchanged.
# This exception is only raised if you explicitly enable strict mode.
ValidationError¶
Raised when setup validation fails.
result = client.validate_setup()
if not result["valid"]:
raise ValidationError(
"Setup validation failed",
details={"issues": result["issues"]}
)
Safety Guarantee¶
If compression fails, the original content passes through unchanged.
This is a core design principle. Your LLM calls never fail due to Headroom:
# Even if SmartCrusher encounters unexpected data:
messages = [
{"role": "tool", "content": "malformed json {{{"}
]
# This will NOT raise an exception
# Instead, the malformed content passes through unchanged
response = client.chat.completions.create(
model="gpt-4o",
messages=messages
)
Logging Errors¶
Enable logging to see error details:
import logging
logging.basicConfig(level=logging.WARNING)
# Now you'll see warnings when compression is skipped:
# WARNING:headroom.transforms.smart_crusher:Skipping compression: invalid JSON
Error Details¶
All Headroom exceptions include a details dict with context:
try:
client = HeadroomClient(...)
except HeadroomError as e:
print(f"Error: {e}")
print(f"Type: {type(e).__name__}")
print(f"Details: {e.details}")
# Details might include:
# - field: which config field caused the error
# - provider: which provider was involved
# - model: which model was requested
# - original_error: underlying exception
Best Practices¶
1. Catch Specific Exceptions¶
# Good: catch specific exceptions
try:
response = client.chat.completions.create(...)
except ConfigurationError:
# Handle config issues
pass
except ProviderError:
# Handle provider issues
pass
# Avoid: catching all exceptions
try:
response = client.chat.completions.create(...)
except Exception:
# Too broad - might hide real bugs
pass
2. Let StorageError Pass¶
# Storage errors don't affect core functionality
try:
metrics = client.get_metrics()
except StorageError:
metrics = [] # Continue without historical metrics
3. Validate on Startup¶
client = HeadroomClient(...)
# Validate once at startup
result = client.validate_setup()
if not result["valid"]:
raise SystemExit(f"Headroom setup invalid: {result['issues']}")
# Then use client normally
response = client.chat.completions.create(...)
Debugging¶
Enable Debug Logging¶
import logging
logging.basicConfig(level=logging.DEBUG)
# Shows detailed transform decisions
# DEBUG:headroom.transforms.smart_crusher:Analyzing 1000 items...
# DEBUG:headroom.transforms.smart_crusher:Kept 15 items (errors: 2, anomalies: 3)