Error Handling & Exceptions¶
folioman-client provides a focused, predictable exception hierarchy derived from FoliomanError. This allows applications to distinguish between network errors, authentication failures, missing resources, and server faults.
Exception Hierarchy¶
graph TD
Exception[Python Exception]
Exception --> FoliomanError[FoliomanError]
FoliomanError --> FoliomanAuthError[FoliomanAuthError]
FoliomanError --> FoliomanNotFoundError[FoliomanNotFoundError]
FoliomanError --> FoliomanAPIError[FoliomanAPIError]
Exception Classes¶
FoliomanError¶
The common ancestor of all SDK exceptions. Catching FoliomanError guarantees you intercept any client-specific exception.
FoliomanAuthError¶
class FoliomanAuthError(FoliomanError):
"""Raised when authentication fails (invalid credentials, expired/rejected token refresh)."""
- When Raised:
- Invalid username or password supplied during initial token pair generation (
HTTP 401on/api/auth/token/pair). - Refresh token expired, rejected, or revoked (
HTTP 401on/api/auth/token/refresh). - Malformed authentication payload returned by the server.
- Connection or network failure while requesting tokens.
- Invalid username or password supplied during initial token pair generation (
- Recommended Action:
- Prompt advisor or system operator to re-authenticate or verify credentials.
- Clear cached tokens or invalidate session state.
FoliomanNotFoundError¶
class FoliomanNotFoundError(FoliomanError):
"""Raised when the requested resource is not found (HTTP 404)."""
- When Raised:
- The requested investor ID, security ID, or transaction does not exist (
HTTP 404).
- The requested investor ID, security ID, or transaction does not exist (
- Recommended Action:
- Handle missing resources gracefully (e.g. return HTTP 404 to your web client, skip entity processing, or create the record).
FoliomanAPIError¶
class FoliomanAPIError(FoliomanError):
def __init__(
self,
message: str,
status_code: int,
response_data: Any | None = None,
) -> None:
...
- Attributes:
status_code(int): The exact HTTP status code returned by the server (e.g.400,403,422,500).response_data(Any | None): The parsed JSON payload or raw text string returned by the server detailing the error.
- When Raised:
- Business rule violations (
HTTP 400). - Unprocessable entity validation errors (
HTTP 422). - Upstream server failures or database connectivity issues (
HTTP 500,502,503). - Response payload is not valid JSON.
- Business rule violations (
Error Handling Examples¶
Granular Try/Except Pattern¶
import asyncio
from folioman_client import (
FoliomanClient,
FoliomanAuthError,
FoliomanNotFoundError,
FoliomanAPIError,
FoliomanError,
)
async def fetch_investor_safe(investor_id: int) -> None:
async with FoliomanClient.from_env() as client:
try:
investor = await client.investors.get(investor_id)
print(f"Loaded: {investor.name}")
except FoliomanAuthError as exc:
print(f"Authentication failed: {exc}. Please check your credentials.")
except FoliomanNotFoundError:
print(f"Investor with ID {investor_id} does not exist.")
except FoliomanAPIError as exc:
print(f"API Error [{exc.status_code}]: {exc}")
if exc.status_code == 422:
print(f"Validation details: {exc.response_data}")
except FoliomanError as exc:
print(f"Generic Folioman client error: {exc}")
except Exception as exc:
print(f"Unexpected application error: {exc}")
if __name__ == "__main__":
asyncio.run(fetch_investor_safe(9999))