From 2b2d6d7aad8b8fc4b62a685171a1a38cfbf810ed Mon Sep 17 00:00:00 2001 From: mateo-berri <277851410+mateo-berri@users.noreply.github.com> Date: Thu, 20 Aug 2026 15:35:20 -0700 Subject: [PATCH] fix(proxy): apply DB-persisted safe litellm settings on every worker's config reload Peer workers previously kept their startup value for block_requests_for_models_without_pricing until a restart, so a toggle from the UI only took effect on the worker that served the request. --- litellm/proxy/proxy_server.py | 13 ++++++++++ .../test_cost_tracking_settings.py | 26 +++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/litellm/proxy/proxy_server.py b/litellm/proxy/proxy_server.py index 12d0f13ebdd..36033f0ff30 100644 --- a/litellm/proxy/proxy_server.py +++ b/litellm/proxy/proxy_server.py @@ -6823,6 +6823,19 @@ class ProxyConfig: if self._should_load_db_object(object_type="config_overrides"): await self._init_hashicorp_vault_config_override(prisma_client=prisma_client) + await self._apply_safe_litellm_settings_overrides_from_db(prisma_client=prisma_client) + + async def _apply_safe_litellm_settings_overrides_from_db(self, prisma_client: PrismaClient) -> None: + config_record: Final = await get_config_param(prisma_client, "litellm_settings") + if config_record is None or config_record.param_value is None: + return + raw_settings: Final = config_record.param_value + litellm_settings: Final = json.loads(raw_settings) if isinstance(raw_settings, str) else raw_settings + if not isinstance(litellm_settings, dict): + return + for key, value in litellm_settings.items(): + if key in LITELLM_SETTINGS_SAFE_DB_OVERRIDES: + setattr(litellm, key, value) async def _init_semantic_filter_settings_in_db(self, prisma_client: PrismaClient): """ diff --git a/tests/test_litellm/proxy/management_endpoints/test_cost_tracking_settings.py b/tests/test_litellm/proxy/management_endpoints/test_cost_tracking_settings.py index ff80bbe4938..8dfc83760b7 100644 --- a/tests/test_litellm/proxy/management_endpoints/test_cost_tracking_settings.py +++ b/tests/test_litellm/proxy/management_endpoints/test_cost_tracking_settings.py @@ -740,6 +740,32 @@ class TestBlockRequestsForModelsWithoutPricing: assert litellm.block_requests_for_models_without_pricing is True + @pytest.mark.asyncio + async def test_periodic_db_sync_applies_flag_to_peer_worker(self): + """The ~10s reconcile loop runs _init_non_llm_objects_in_db on every worker; it must apply + the persisted flag so peers converge without a restart.""" + from types import SimpleNamespace + + from litellm.proxy.proxy_server import ProxyConfig + + config_record = SimpleNamespace( + param_value={"block_requests_for_models_without_pricing": True, "unsafe_key": "x"} + ) + with ( + patch.object(litellm, "block_requests_for_models_without_pricing", False), + patch.object( + ProxyConfig, + "_should_load_db_object", + side_effect=lambda object_type: object_type == "config_overrides", + ), + patch.object(ProxyConfig, "_init_hashicorp_vault_config_override", AsyncMock()), + patch("litellm.proxy.proxy_server.get_config_param", AsyncMock(return_value=config_record)), + ): + await ProxyConfig()._init_non_llm_objects_in_db(prisma_client=MagicMock()) + + assert litellm.block_requests_for_models_without_pricing is True + assert not hasattr(litellm, "unsafe_key") + @pytest.mark.asyncio async def test_patch_requires_store_model_in_db(self): with (