diff --git a/litellm/proxy/proxy_server.py b/litellm/proxy/proxy_server.py index 45c4ddf6f3f..351f19e1638 100644 --- a/litellm/proxy/proxy_server.py +++ b/litellm/proxy/proxy_server.py @@ -8509,11 +8509,16 @@ class ProxyConfig: "is ignored. %s", key, "The config file's value applies. Remove the stored copy with POST /config/field/delete." - if self.settings.owned_by_config(key) + if self._config_sets_ignored_db_key(key) else "Set it in the config file to use it, or remove it with POST /config/field/delete.", ) self._warned_unmanaged_keys = unmanaged + def _config_sets_ignored_db_key(self, key: str) -> bool: + return self.settings.owned_by_config(key) or ( + key in _GENERAL_SETTINGS_UI_LITELLM_FIELDS and self.config_owns(section_name="litellm_settings", key=key) + ) + def _prepared_db_settings_values(self, section: Section, value: object) -> Mapping[str, SettingsJsonValue]: scrubbed: Final = _scrub_db_overlay_remote_module_loads(section=section, db_value=value) return _as_settings_mapping(scrubbed) diff --git a/tests/unit/proxy/proxy_server/test_proxy_config.py b/tests/unit/proxy/proxy_server/test_proxy_config.py index 08c43164f47..a4f81c1645b 100644 --- a/tests/unit/proxy/proxy_server/test_proxy_config.py +++ b/tests/unit/proxy/proxy_server/test_proxy_config.py @@ -4403,6 +4403,25 @@ async def test_ProxyConfig__update_general_settings_warns_about_an_ignored_store ] +@pytest.mark.asyncio +async def test_ProxyConfig__update_general_settings_says_the_config_file_applies_for_a_stored_ui_field_it_sets( + monkeypatch: pytest.MonkeyPatch, caplog: pytest.LogCaptureFixture +) -> None: + pc: Final = ProxyConfig() + pc._load_yaml_settings_stores({"general_settings": {}, "litellm_settings": {"budget_rollover": True}}) + monkeypatch.setattr("litellm.proxy.proxy_server.general_settings", pc.settings) + + with caplog.at_level(logging.WARNING, logger="LiteLLM Proxy"): + await pc._update_general_settings({"budget_rollover": False}) + + warnings: Final = [record.getMessage() for record in caplog.records if "budget_rollover" in record.getMessage()] + assert warnings == [ + "general_settings.budget_rollover is stored in the database, but the proxy does not apply that stored " + "value, so it is ignored. The config file's value applies. Remove the stored copy with POST " + "/config/field/delete." + ] + + def _paused_scheduler(monkeypatch): from apscheduler.schedulers.asyncio import AsyncIOScheduler @@ -5011,8 +5030,8 @@ async def test_ProxyConfig__update_config_from_db_keeps_keys_the_config_file_omi @pytest.mark.asyncio @pytest.mark.parametrize("ui_settings_already_synced", [False, True]) async def test_ProxyConfig_add_deployment_continues_after_null_pass_through_endpoints( - monkeypatch, ui_settings_already_synced -): + monkeypatch: pytest.MonkeyPatch, ui_settings_already_synced: bool +) -> None: from litellm.proxy import proxy_server pc = ProxyConfig() diff --git a/tests/unit/proxy/test_proxy_server_endpoints_and_startup.py b/tests/unit/proxy/test_proxy_server_endpoints_and_startup.py index cdc3887448e..f33a38df00d 100644 --- a/tests/unit/proxy/test_proxy_server_endpoints_and_startup.py +++ b/tests/unit/proxy/test_proxy_server_endpoints_and_startup.py @@ -3757,7 +3757,9 @@ async def test_db_reload_keeps_the_resolved_value_of_a_config_owned_env_referenc @pytest.mark.asyncio -async def test_db_reload_of_a_json_string_general_settings_row_reports_no_ignored_keys(monkeypatch): +async def test_db_reload_of_a_json_string_general_settings_row_reports_no_ignored_keys( + monkeypatch: pytest.MonkeyPatch, +) -> None: from litellm.proxy import proxy_server as proxy_server_module from litellm.proxy.proxy_server import ProxyConfig