Spaces:
Sleeping
User Preferences Update Bug - Root Cause & Fix
Issue Summary
User preferences updates (theme, favorite_apps) were not being saved to the database despite the API returning 200 OK responses.
Root Cause
Duplicate Route Definitions
The auth.py file had TWO different endpoints with the same route path:
OLD Endpoint (Line 847) -
PUT /me/preferences- Function:
update_user_preferences() - Input: Generic
dict - Output:
UserProfile(no preference fields) - Only handled:
last_active_project_id - Ignored:
theme,favorite_apps, and all other preference fields
- Function:
NEW Endpoint (Line 1242) -
PUT /me/preferences- Function:
update_my_preferences() - Input:
UserPreferencesUpdateschema - Output:
UserPreferencesResponse(includes all preference fields) - Handles:
favorite_apps,theme,language, notifications, etc.
- Function:
Why It Failed
When FastAPI registers routes, only the first matching route is registered. The old endpoint (line 847) was being called for all /me/preferences PUT requests, which:
- Accepted the request body as a dict
- Only looked for
last_active_project_id - Silently ignored
theme,favorite_apps, and other fields - Returned
UserProfilewithout preference data - This is why the browser console showed:
favoriteAppsCount: 0, favoriteAppsJson: undefined
Evidence from Logs
Browser Console (browserconsole.txt)
Line 48: [DATA] Updating user preferences {theme: 'light', favoriteAppsJson: undefined}
Line 49: PUT https://kamau1-swiftops-backend.hf.space/api/v1/auth/me/preferences
Line 50: PUT .../api/v1/auth/me/preferences β 200 (625ms)
Line 51: [DATA] User preferences updated successfully {updatedFields: Array(1), theme: undefined, favoriteAppsCount: 0, favoriteAppsJson: undefined}
The request succeeded (200 OK) but the response didn't contain the updated data.
Server Logs (runtimeerror.txt)
Line 35: PUT /api/v1/auth/me/preferences HTTP/1.1" 200 OK
Line 181: PUT /api/v1/auth/me/preferences HTTP/1.1" 200 OK
Line 260: PUT /api/v1/auth/me/preferences HTTP/1.1" 200 OK
Line 264: PUT /api/v1/auth/me/preferences HTTP/1.1" 200 OK
Multiple successful requests, but the old endpoint was being called.
The Fix
Changes Made
1. Added last_active_project_id to UserPreferencesUpdate schema
- File:
src/app/schemas/user_preferences.py - Added the field so the preferences endpoint can handle project context updates
2. Enhanced the preferences endpoint with project validation
- File:
src/app/api/v1/auth.py(line 1242+) - Added validation logic for
last_active_project_id:- Prevents platform admins from setting project context
- Verifies user is assigned to the project
- Verifies project exists and is active
- Updated field exclusion list to skip validated fields
3. Removed the old duplicate endpoint entirely
- File:
src/app/api/v1/auth.py(previously line 847-1020) - Deleted the old
PUT /me/active-projectendpoint - No longer needed since the new endpoint handles everything
Result: Single Unified Endpoint
Now there is ONE endpoint that handles ALL user preference updates:
PUT /api/v1/auth/me/preferences
- Input:
UserPreferencesUpdateschema - Output:
UserPreferencesResponse - Handles:
- β
favorite_apps- Array of app codes (max 6, role-validated) - β
theme- 'light', 'dark', or 'auto' - β
language- Language code - β
last_active_project_id- Project context (validated) - β
email_notifications- Boolean - β
push_notifications- Boolean - β
sms_notifications- Boolean - β
dashboard_widgets- Array of widget codes - β
default_tickets_view- 'list', 'kanban', or 'calendar' - β All other preference fields
- β
Response Format
The endpoint now returns UserPreferencesResponse which includes:
{
"id": "uuid",
"user_id": "uuid",
"favorite_apps": ["dashboard", "organizations", "users", "activity"],
"theme": "light",
"language": "en",
"email_notifications": true,
"last_active_project_id": "uuid",
...
}
Testing Required
Restart the backend server to load the updated route
Test theme updates:
- Toggle theme from dark to light
- Verify database
user_preferences.themecolumn updates - Verify API response contains updated theme
Test favorite apps updates:
- Add/remove favorite apps
- Verify database
user_preferences.favorite_appscolumn updates - Verify API response contains updated favorite_apps array
Test project context updates:
- Switch active project
- Verify database
user_preferences.last_active_project_idcolumn updates - Verify API response contains updated project ID
Migration Notes
Breaking Changes
- Removed:
PUT /me/active-projectendpoint (was never in production) - Use instead:
PUT /me/preferencesfor all preference updates
Unified Endpoint
- Route:
PUT /api/v1/auth/me/preferences - Purpose: Update all user preferences in one place
- Supports: All preference fields including
last_active_project_id
Database Schema
The fix doesn't require any database changes. The user_preferences table already has all the necessary columns:
favorite_apps(JSONB array)theme(VARCHAR)language(VARCHAR)email_notifications(BOOLEAN)- etc.
The issue was purely in the routing layer.