Fix Issue 10: Document error handling pattern

- Analyzed error handling - found complete exception hierarchy already exists
- Confirmed global exception handlers registered and working
- Documented dual error handling pattern in ARCHITECTURE.md section 4.5:
  * HTTPException for simple validation and HTTP-level errors
  * Custom AniWorldAPIException for business logic with rich context
- Clarified when to use each type with examples
- Finding: Error handling was already well-structured, just needed documentation

Architecture Decision: Dual pattern is intentional and correct.
Tests passing (auth flow verified)
This commit is contained in:
2026-01-24 21:25:48 +01:00
parent c4080e4e57
commit 4abaf8def7
2 changed files with 85 additions and 6 deletions

View File

@@ -468,6 +468,75 @@ def get_download_service() -> DownloadService:
return _download_service_instance
```
### 4.5 Error Handling Pattern
**Architecture Decision**: Dual error handling approach based on exception source.
The application uses two complementary error handling mechanisms:
1. **FastAPI HTTPException** - For simple validation and HTTP-level errors
2. **Custom Exception Hierarchy** - For business logic and service-level errors with rich context
#### Exception Hierarchy
```python
# Base exception with HTTP status mapping
AniWorldAPIException(message, status_code, error_code, details)
AuthenticationError (401)
AuthorizationError (403)
ValidationError (422)
NotFoundError (404)
ConflictError (409)
BadRequestError (400)
RateLimitError (429)
ServerError (500)
DownloadError
ConfigurationError
ProviderError
DatabaseError
```
#### When to Use Each
**Use HTTPException for:**
- Simple parameter validation (missing fields, wrong type)
- Direct HTTP-level errors (401, 403, 404 without business context)
- Quick endpoint-specific failures
**Use Custom Exceptions for:**
- Service-layer business logic errors (AnimeServiceError, ConfigServiceError)
- Errors needing rich context (details dict, error codes)
- Errors that should be logged with specific categorization
- Cross-cutting concerns (authentication, authorization, rate limiting)
**Example:**
```python
# Simple validation - Use HTTPException
if not series_key:
raise HTTPException(status_code=400, detail="series_key required")
# Business logic error - Use custom exception
try:
await anime_service.add_series(series_key)
except AnimeServiceError as e:
raise ServerError(
message=f"Failed to add series: {e}",
error_code="ANIME_ADD_FAILED",
details={"series_key": series_key}
)
```
#### Global Exception Handlers
All custom exceptions are automatically handled by global middleware that:
- Converts exceptions to structured JSON responses
- Logs errors with appropriate severity
- Includes request ID for tracking
- Provides consistent error format
**Source**: [src/server/exceptions/\_\_init\_\_.py](../src/server/exceptions/__init__.py), [src/server/middleware/error_handler.py](../src/server/middleware/error_handler.py)
Source: [src/server/services/download_service.py](../src/server/services/download_service.py)
---