fix(proxy): say the config file applies for a stored copy of a UI field config.yaml sets under litellm_settings

This commit is contained in:
mateo-berri 2026-10-29 12:17:00 -07:00
parent edc32593e9
commit 2dc56dd784
3 changed files with 30 additions and 4 deletions

View file

@ -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)

View file

@ -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()

View file

@ -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