Backend API Error Catalog Summary
Date: 2026-02-13 Purpose: Improve user-facing error messages for Phase 3e.4 (Engagement & Polish)
Quick Stats
- Total Files: 12 API modules
- Total HTTPExceptions: 75 errors
- User-Friendly Messages: 40 (53%)
- Generic
str(e)Messages: 35 (47%) ⚠️
Priority Action Items
🔴 Critical: Replace Generic Error Messages (35 instances)
Files with most str(e) errors:
auth.py— 12 instances (signup, signin, profile, consent)members.py— 7 instances (invites, roles)groups.py— 3 instances (CRUD operations)spaces.py— 3 instances (CRUD operations)tasks.py— 1 instance (state transitions)skills.py— 2 instances (validation)
🟡 Medium: Improve Error Context
Skills API (10 errors):
- 2 errors expose raw exceptions:
Invalid definition: {e} - 2 errors return 500 instead of 400:
Failed to update/delete skill
SSO API (5 errors):
- 1 error lacks context:
Invalid SSO token→ add reason (expired, malformed, etc.)
🟢 Low: Add Error Codes for Client-Side Handling
Well-structured modules (keep as reference):
chat.py— 12 user-friendly messagesinterfaces.py— 9 contextual messages with parametersoauth.py— 3 clear configuration/validation errors
Implementation Plan
Step 1: Create Error Constants Module
# backend/errors.py
class ErrorMessage:
"""User-friendly error message constants"""
# Auth errors
AUTH_INVALID_CREDENTIALS = "Invalid email or password"
AUTH_EMAIL_EXISTS = "An account with this email already exists"
AUTH_WEAK_PASSWORD = "Password must be at least 8 characters"
# Group errors
GROUP_NAME_REQUIRED = "Group name is required"
GROUP_ALREADY_EXISTS = "You are already in a group"
# Invite errors
INVITE_EMAIL_DUPLICATE = "This email has already been invited"
INVITE_CANNOT_SELF = "You cannot invite yourself"
INVITE_EXPIRED = "This invitation has expired"
Step 2: Map Exceptions to Messages
# backend/utils/error_handler.py
def get_user_friendly_message(exception: Exception) -> str:
"""Map internal exceptions to user-friendly messages"""
error_map = {
"User already exists": ErrorMessage.AUTH_EMAIL_EXISTS,
"Invalid login credentials": ErrorMessage.AUTH_INVALID_CREDENTIALS,
# ... etc
}
return error_map.get(str(exception), "An unexpected error occurred")
Step 3: Update API Handlers
Before:
except Exception as e:
raise HTTPException(status_code=400, detail=str(e))
After:
except Exception as e:
friendly_message = get_user_friendly_message(e)
logger.error(f"Operation failed: {e}", exc_info=True) # Log full error
raise HTTPException(status_code=400, detail=friendly_message)
Step 4: Add Structured Error Responses (Future)
# With error codes for client-side handling
{
"error": "DUPLICATE_EMAIL",
"message": "An account with this email already exists",
"code": "E400_AUTH_001",
"field": "email" # Optional, for form validation
}
Testing Checklist
- Backend tests pass with new error messages
- Frontend displays user-friendly errors in toast notifications
- Error messages don't expose internal implementation details
- No PII (personally identifiable information) in error logs
- Error codes documented in
docs/api.md
Files to Update
Backend (Python)
-
backend/errors.py— create with message constants -
backend/utils/error_handler.py— create exception mapper -
backend/api/auth.py— 12 errors -
backend/api/groups.py— 3 errors -
backend/api/members.py— 7 errors -
backend/api/spaces.py— 3 errors -
backend/api/tasks.py— 1 error -
backend/api/skills.py— 2 errors + 2 500s
Frontend (TypeScript)
-
frontend/src/lib/api.ts— update error interceptor -
frontend/src/hooks/use-toast.ts— friendly error formatting - Test error display in UI components
Documentation
-
docs/api.md— document error codes and messages -
CHANGELOG.md— note breaking changes if error format changes
Reference: Current Error Distribution
| Status Code | Count | Action |
|---|---|---|
| 400 | 35 | Replace 20 generic messages, keep 15 good ones |
| 401 | 4 | Add more context (expired token, invalid credentials) |
| 403 | 1 | Already good: "Only group parents can cancel invites" |
| 404 | 29 | Mostly good, standardize format |
| 409 | 1 | Already good: "Skill '{name}' already exists" |
| 500 | 2 | Convert to 400 with specific messages |
| 501 | 1 | Already good: "Google OAuth not configured" |
| 502 | 1 | Add retry logic, improve message |
Output Files:
/tmp/ERROR_CATALOG.md— Full catalog with all 75 errors categorized/tmp/error_catalog.json— Machine-readable format for tooling/tmp/ERROR_SUMMARY.md— This summary document
Next: Copy catalog to docs/errors/ and implement Step 1-3 in Phase 3e.4