Documentation Index
Fetch the complete documentation index at: https://docs.law4devs.eu/llms.txt
Use this file to discover all available pages before exploring further.
Overview
All SDK errors inherit from Law4DevsError. Each exception class maps to a specific HTTP status code or error condition. The SDK automatically retries transient errors (429 and 5xx) with exponential backoff before raising.
Exception Hierarchy
Law4DevsError
├── NotFoundError (HTTP 404)
├── ValidationError (HTTP 400 / 422)
├── RateLimitError (HTTP 429)
└── ServerError (HTTP 500 / 502 / 503 / 504)
All exceptions expose a status_code attribute containing the underlying HTTP status code.
from law4devs.exceptions import (
Law4DevsError,
NotFoundError,
ValidationError,
RateLimitError,
ServerError,
)
Exception Reference
Law4DevsError
Base class for all SDK exceptions. Catch this to handle any API error.
| Attribute | Type | Description |
|---|
status_code | int | HTTP status code |
message | str | Human-readable error message |
NotFoundError
Raised when the requested resource does not exist (HTTP 404).
try:
article = client.articles.get("gdpr", 9999)
except NotFoundError as e:
print(f"Article not found: {e.message}")
ValidationError
Raised when the request parameters are invalid (HTTP 400 or 422).
try:
page = client.articles.list("gdpr", per_page=999) # exceeds max
except ValidationError as e:
print(f"Bad request: {e.message}")
RateLimitError
Raised when the rate limit is exceeded and all retries are exhausted (HTTP 429).
try:
results = client.search.query("encryption")
except RateLimitError as e:
print(f"Rate limited. Retry after: {e.retry_after} seconds")
ServerError
Raised when the server returns a 5xx response and all retries are exhausted.
try:
page = client.frameworks.list()
except ServerError as e:
print(f"Server error {e.status_code}: {e.message}")
Auto-Retry Behaviour
The SDK automatically retries failed requests on HTTP 429 and 5xx responses. Retries use exponential backoff with jitter.
- Default retries: 3
- Backoff: 1s, 2s, 4s (with jitter)
- Retried status codes: 429, 500, 502, 503, 504
If all retries are exhausted, the appropriate exception (RateLimitError or ServerError) is raised.
Configure the retry count at construction time:
from law4devs import Law4DevsClient
# Disable retries
client = Law4DevsClient(max_retries=0)
# More retries for a long-running batch job
client = Law4DevsClient(max_retries=5)
Practical Patterns
Handle a missing resource
from law4devs import Law4DevsClient
from law4devs.exceptions import NotFoundError
client = Law4DevsClient()
try:
article = client.articles.get("gdpr", 999)
except NotFoundError:
print("That article doesn't exist")
safe_get helper
A utility that returns None instead of raising on 404:
from law4devs.exceptions import NotFoundError
def safe_get_article(client, framework_slug, article_number):
try:
return client.articles.get(framework_slug, article_number)
except NotFoundError:
return None
article = safe_get_article(client, "gdpr", 999)
if article is None:
print("Not found")
else:
print(article.title)
Catch all API errors
from law4devs.exceptions import Law4DevsError
try:
page = client.frameworks.list()
except Law4DevsError as e:
print(f"API error {e.status_code}: {e.message}")
Handle rate limits explicitly
import time
from law4devs.exceptions import RateLimitError
def fetch_with_backoff(client, framework_slug):
for attempt in range(5):
try:
return list(client.articles.iter(framework_slug))
except RateLimitError as e:
wait = getattr(e, "retry_after", 2 ** attempt)
print(f"Rate limited. Waiting {wait}s (attempt {attempt + 1}/5)")
time.sleep(wait)
raise RuntimeError("Exhausted retries")
Distinguish error types
from law4devs.exceptions import (
NotFoundError,
ValidationError,
RateLimitError,
ServerError,
Law4DevsError,
)
try:
result = client.articles.get("gdpr", article_number)
except NotFoundError:
print("Article not found — check the article number")
except ValidationError as e:
print(f"Invalid parameters: {e.message}")
except RateLimitError:
print("Too many requests — slow down or add an API key")
except ServerError as e:
print(f"Server problem ({e.status_code}) — try again later")
except Law4DevsError as e:
print(f"Unexpected error {e.status_code}: {e.message}")
Validate a framework slug before use
from law4devs.exceptions import NotFoundError
def framework_exists(client, slug):
try:
client.frameworks.get(slug)
return True
except NotFoundError:
return False
if not framework_exists(client, "unknown-framework"):
print("Framework not found")
Timeout Errors
Network timeouts raise Python’s built-in TimeoutError (not a Law4DevsError). Configure the timeout per client:
# Allow up to 60 seconds per request
client = Law4DevsClient(timeout=60)
try:
page = client.frameworks.list()
except TimeoutError:
print("Request timed out — the server may be slow")
For batch jobs that process thousands of items, set max_retries=5 and a generous timeout=60. The SDK will handle intermittent failures automatically.
404 responses are not retried automatically — they indicate a resource genuinely does not exist, not a transient failure.