Morphee Backend API Error Catalog
Generated: 2026-02-13 Total Files: 12 Total Errors: 75
This catalog documents all HTTPException error messages in the backend API for potential user-facing error message improvements.
Summary by Status Code
| Status Code | Count | Description |
|---|---|---|
| 400 | 35 | Bad Request — validation or business logic errors |
| 401 | 4 | Unauthorized — authentication failures |
| 403 | 1 | Forbidden — permission denied |
| 404 | 29 | Not Found — resource does not exist |
| 409 | 1 | Conflict — duplicate resource |
| 500 | 2 | Internal Server Error — unexpected failures |
| 501 | 1 | Not Implemented — feature not configured |
| 502 | 1 | Bad Gateway — upstream service error |
Errors by Category
Authentication & Authorization (backend/api/auth.py)
12 errors — signup, signin, tokens, profile, consent
| Line | Function | Status | Message | Notes |
|---|---|---|---|---|
| 80 | signup | 400 | str(e) | Generic exception from auth service |
| 104 | signin | 401 | str(e) | Invalid credentials |
| 130 | refresh | 401 | No refresh token provided | Missing refresh token |
| 143 | (middleware) | 401 | str(e) | Token validation failure |
| 194 | get_profile | 404 | str(e) | User profile not found |
| 207 | update_profile | 400 | str(e) | Profile update validation |
| 221 | change_password | 400 | str(e) | Password change failure |
| 241 | delete_account | 400 | Must send confirmation: "DELETE" to proceed | Confirmation mismatch |
| 251 | delete_account | 400 | str(e) | Account deletion failure |
| 294 | (consent) | 400 | str(e) | Consent operation error |
| 332 | grant_consent | 400 | str(e) | Grant consent failure |
| 346 | withdraw_consent | 400 | str(e) | Withdraw consent failure |
Recommendations:
- Replace
str(e)with friendly messages like "Invalid email or password", "Email already registered", etc. - Add specific error codes for different auth failures
Chat & Conversations (backend/api/chat.py)
12 errors — conversations, messages, regeneration, approvals
| Line | Function | Status | Message | Notes |
|---|---|---|---|---|
| 359 | update_conversation | 404 | Conversation not found | ✅ User-friendly |
| 375 | get_conversation_messages | 404 | Conversation not found | ✅ User-friendly |
| 391 | update_message | 404 | Message not found | ✅ User-friendly |
| 406 | pin_message | 400 | Unable to pin message (not found or limit reached) | ✅ Good context |
| 421 | unpin_message | 404 | Message not found | ✅ User-friendly |
| 448 | regenerate_response | 404 | Conversation not found | ✅ User-friendly |
| 455 | regenerate_response | 400 | Not enough messages to regenerate | ✅ User-friendly |
| 459 | regenerate_response | 400 | Last message is not an assistant message | ✅ User-friendly |
| 469 | regenerate_response | 400 | No user message found to regenerate from | ✅ User-friendly |
| 596 | delete_conversation | 404 | Conversation not found | ✅ User-friendly |
| 618 | decide_approval | 404 | Approval request not found or expired | ✅ User-friendly |
| 641 | handle_component_event | 400 | Local events are handled client-side | Internal error |
Recommendations:
- Chat errors are already well-structured!
- Consider adding error codes for client-side filtering
Groups (backend/api/groups.py)
6 errors — group CRUD operations
| Line | Function | Status | Message | Notes |
|---|---|---|---|---|
| 29 | create_group | 400 | User is already in a group | ✅ User-friendly |
| 35 | create_group | 400 | User record not found | Internal error |
| 43 | create_group | 400 | str(e) | Generic database error |
| 59 | get_my_group | 404 | Group not found | ✅ User-friendly |
| 85 | update_my_group | 400 | str(e) | Generic update error |
| 102 | delete_my_group | 404 | Group not found or could not be deleted | ✅ Good context |
Recommendations:
- Replace
str(e)with specific messages (validation, name taken, etc.)
Members & Invites (backend/api/members.py)
9 errors — invitations, roles, member management
| Line | Function | Status | Message | Notes |
|---|---|---|---|---|
| 45 | create_invite | 400 | str(e) | Invite creation errors |
| 65 | cancel_invite | 403 | Only group parents can cancel invites | ✅ Permission error |
| 72 | cancel_invite | 404 | Invite not found or already processed | ✅ User-friendly |
| 86 | accept_invite | 400 | User record not found | Internal error |
| 93 | accept_invite | 400 | str(e) | Accept errors |
| 106 | decline_invite | 400 | str(e) | Decline errors |
| 132 | update_member_role | 400 | str(e) | Role update errors |
| 146 | remove_member | 404 | Member not found | ✅ User-friendly |
| 152 | remove_member | 400 | str(e) | Removal errors |
Recommendations:
- Map
str(e)to specific cases: "Email already invited", "Invite expired", "Cannot remove yourself", etc.
Spaces (backend/api/spaces.py)
4 errors — space CRUD operations
| Line | Function | Status | Message | Notes |
|---|---|---|---|---|
| 32 | create_space | 400 | str(e) | Space creation errors |
| 64 | get_space | 404 | Space not found | ✅ User-friendly |
| 82 | update_space | 400 | str(e) | Space update errors |
| 100 | delete_space | 404 | Space not found | ✅ User-friendly |
Recommendations:
- Add specific validation messages for name conflicts, parent space errors
Tasks (backend/api/tasks.py)
3 errors — task CRUD operations
| Line | Function | Status | Message | Notes |
|---|---|---|---|---|
| 45 | get_task | 404 | Task not found | ✅ User-friendly |
| 81 | update_task | 400 | str(e) | State transition errors |
| 131 | delete_task | 404 | Task not found | ✅ User-friendly |
Recommendations:
- Map task state machine errors to messages like "Cannot pause completed task"
Skills (backend/api/skills.py)
10 errors — skill definitions, validation, CRUD
| Line | Function | Status | Message | Notes |
|---|---|---|---|---|
| 56 | get_skill | 404 | Skill not found | ✅ User-friendly |
| 71 | create_skill | 400 | Invalid definition: {e} | ⚠️ Exposes exception |
| 81 | create_skill | 400 | Validation errors: {'; '.join(errors)} | ✅ Detailed validation |
| 97 | create_skill | 409 | Skill '{body.name}' already exists | ✅ User-friendly |
| 121 | update_skill | 404 | Skill not found | ✅ User-friendly |
| 134 | update_skill | 400 | Invalid definition: {e} | ⚠️ Exposes exception |
| 143 | update_skill | 400 | Validation errors: {'; '.join(errors)} | ✅ Detailed validation |
| 148 | update_skill | 500 | Failed to update skill | ⚠️ Generic 500 |
| 180 | delete_skill | 404 | Skill not found | ✅ User-friendly |
| 195 | delete_skill | 500 | Failed to delete skill | ⚠️ Generic 500 |
Recommendations:
- Sanitize
{e}to avoid exposing internal errors - Add error codes for specific validation failures
- Investigate 500 errors — should be 400s with specific messages
Interfaces (backend/api/interfaces.py)
9 errors — interface configs, actions
| Line | Function | Status | Message | Notes |
|---|---|---|---|---|
| 83 | get_interface_config | 404 | Interface not found: {interface_name} | ✅ User-friendly |
| 89 | get_interface_config | 404 | No config found for {interface_name} | ✅ User-friendly |
| 114 | save_interface_config | 404 | Interface not found: {interface_name} | ✅ User-friendly |
| 117 | save_interface_config | 400 | Interface {interface_name} is not configurable | ✅ User-friendly |
| 157 | delete_interface_config | 404 | Interface not found: {interface_name} | ✅ User-friendly |
| 168 | delete_interface_config | 404 | No config found for {interface_name} | ✅ User-friendly |
| 185 | get_interface | 404 | Interface not found: {interface_name} | ✅ User-friendly |
| 215 | execute_action | 404 | Interface not found: {action_execution.interface_name} | ✅ User-friendly |
| 228 | execute_action | 404 | Action not found: {action_execution.action_name} | ✅ User-friendly |
Recommendations:
- Interfaces have excellent error messages!
OAuth (backend/api/oauth.py)
3 errors — Google OAuth configuration, redirect URIs
| Line | Function | Status | Message | Notes |
|---|---|---|---|---|
| 68 | google_authorize | 501 | Google OAuth not configured | ✅ Configuration error |
| 80 | google_authorize | 400 | Redirect URI domain not allowed | ✅ Security error |
| 85 | google_authorize | 400 | Invalid redirect URI scheme: {parsed.scheme} | ✅ Validation error |
Recommendations:
- OAuth errors are well-structured!
SSO (backend/api/sso.py)
5 errors — SSO provider discovery, authorization, callbacks
| Line | Function | Status | Message | Notes |
|---|---|---|---|---|
| 84 | list_providers | 502 | Failed to query auth provider settings | ⚠️ Upstream error |
| 97 | sso_authorize | 400 | Unsupported provider: {provider} | ✅ User-friendly |
| 109 | sso_authorize | 400 | Invalid redirect URI scheme: {parsed.scheme} | ✅ Validation error |
| 119 | sso_authorize | 400 | Invalid redirect URI: hostname not allowed | ✅ Security error |
| 149 | sso_callback | 401 | Invalid SSO token | ✅ Auth error |
Recommendations:
- Consider retry logic for 502 errors
- Add more context to "Invalid SSO token" (expired, malformed, etc.)
Notifications (backend/api/notifications.py)
1 error — notification operations
| Line | Function | Status | Message | Notes |
|---|---|---|---|---|
| 53 | mark_read | 404 | Notification not found | ✅ User-friendly |
Onboarding (backend/api/onboarding.py)
1 error — onboarding flow validation
| Line | Function | Status | Message | Notes |
|---|---|---|---|---|
| 146 | onboarding_chat | 400 | User already has a group. Onboarding is not needed. | ✅ User-friendly |
Action Items for Phase 3e.4 (Engagement & Polish)
High Priority (User-Facing)
-
Replace
str(e)in auth.py (12 instances)- Map Supabase auth errors to friendly messages
- Examples: "Email already registered", "Invalid email or password", "Password must be at least 8 characters"
-
Replace
str(e)in groups/members/spaces (10 instances)- Validation errors: "Group name required", "Name must be unique"
- Business logic: "Cannot invite yourself", "Email already invited"
-
Sanitize skill validation errors (2 instances)
- Don't expose raw exception text in
Invalid definition: {e} - Parse and translate to user-friendly messages
- Don't expose raw exception text in
Medium Priority (Developer Experience)
-
Add error codes
- Pattern:
{"error": "CONVERSATION_NOT_FOUND", "message": "...", "code": "E404_CONV"} - Enables client-side error handling and i18n
- Pattern:
-
Investigate 500 errors in skills.py (2 instances)
- Should be 400s with specific messages
- Add better exception handling
Low Priority (Monitoring)
- Add structured logging for all HTTPExceptions
- Log error code, user_id, group_id for debugging
- Don't log PII in error messages
Pattern Analysis
✅ Good Patterns (Keep)
- Specific, contextual messages:
"Conversation not found","Only group parents can cancel invites" - Validation details:
f"Validation errors: {'; '.join(errors)}" - Dynamic context:
f"Interface not found: {interface_name}"
⚠️ Anti-Patterns (Fix)
- Generic
str(e): Exposes internal errors, not user-friendly (35 instances) - 500 for business logic: Use 400 with specific message instead
- Missing context: "Failed to update" → "Failed to update: name already exists"
Error Message Template
# Good
raise HTTPException(
status_code=400,
detail="Space name must be unique within the group"
)
# Bad
raise HTTPException(status_code=400, detail=str(e))
With Error Codes (Future)
raise HTTPException(
status_code=400,
detail={
"error": "DUPLICATE_SPACE_NAME",
"message": "A space with this name already exists in your group",
"field": "name"
}
)
Next Steps:
- Create
backend/errors.pywith error message constants - Map exception types to user-friendly messages
- Update all
str(e)instances - Add error codes for client-side handling
- Document error codes in
docs/api.md