diff --git a/litellm/proxy/ui_crud_endpoints/proxy_setting_endpoints.py b/litellm/proxy/ui_crud_endpoints/proxy_setting_endpoints.py index 7ef6d6b67f..2f7f81a703 100644 --- a/litellm/proxy/ui_crud_endpoints/proxy_setting_endpoints.py +++ b/litellm/proxy/ui_crud_endpoints/proxy_setting_endpoints.py @@ -1061,13 +1061,26 @@ async def update_ui_settings( }, ) - settings_dict = settings.model_dump(exclude_none=True) + # Only include fields the caller actually sent (not Pydantic defaults). + settings_dict = settings.model_dump(exclude_unset=True) # Enforce allowlist and drop anything unexpected - ui_settings = { + incoming = { k: v for k, v in settings_dict.items() if k in ALLOWED_UI_SETTINGS_FIELDS } + # Merge with existing persisted settings so a partial PATCH doesn't + # overwrite fields the caller didn't send. + existing: dict = {} + db_existing = await prisma_client.db.litellm_uisettings.find_unique( + where={"id": "ui_settings"} + ) + if db_existing and db_existing.ui_settings: + raw = db_existing.ui_settings + existing = json.loads(raw) if isinstance(raw, str) else dict(raw) + + ui_settings = {**existing, **incoming} + await prisma_client.db.litellm_uisettings.upsert( where={"id": "ui_settings"}, data={ diff --git a/tests/test_litellm/proxy/ui_crud_endpoints/test_proxy_setting_endpoints.py b/tests/test_litellm/proxy/ui_crud_endpoints/test_proxy_setting_endpoints.py index 31baab0092..f955a6134b 100644 --- a/tests/test_litellm/proxy/ui_crud_endpoints/test_proxy_setting_endpoints.py +++ b/tests/test_litellm/proxy/ui_crud_endpoints/test_proxy_setting_endpoints.py @@ -867,6 +867,7 @@ class TestProxySettingEndpoints: monkeypatch.setattr("litellm.proxy.proxy_server.store_model_in_db", True) mock_prisma = MagicMock() mock_prisma.db.litellm_uisettings.upsert = AsyncMock() + mock_prisma.db.litellm_uisettings.find_unique = AsyncMock(return_value=None) monkeypatch.setattr("litellm.proxy.proxy_server.prisma_client", mock_prisma) payload = {"disable_model_add_for_internal_users": True} @@ -908,6 +909,7 @@ class TestProxySettingEndpoints: monkeypatch.setattr("litellm.proxy.proxy_server.store_model_in_db", True) mock_prisma = MagicMock() mock_prisma.db.litellm_uisettings.upsert = AsyncMock() + mock_prisma.db.litellm_uisettings.find_unique = AsyncMock(return_value=None) monkeypatch.setattr("litellm.proxy.proxy_server.prisma_client", mock_prisma) payload = {