diff --git a/litellm/constants.py b/litellm/constants.py index 87d6fa1a744..fc72689cd47 100644 --- a/litellm/constants.py +++ b/litellm/constants.py @@ -1556,6 +1556,7 @@ LITELLM_SETTINGS_SAFE_DB_OVERRIDES: Final = [ "cost_discount_config", "cost_margin_config", "budget_exceeded_throttle_percentage", + "max_budget", # Every field editable from the Admin UI (proxy_server._GENERAL_SETTINGS_UI_LITELLM_FIELDS) # must be listed here so a DB write from one worker overrides the live litellm attribute on # the others when config reloads; otherwise peer workers stay on their startup value. diff --git a/litellm/proxy/proxy_server.py b/litellm/proxy/proxy_server.py index f79819c76d3..dd3c8a7def1 100644 --- a/litellm/proxy/proxy_server.py +++ b/litellm/proxy/proxy_server.py @@ -6241,8 +6241,8 @@ class ProxyConfig: return current_config elif param_name == "litellm_settings" and isinstance(db_param_value, dict): for key, value in db_param_value.items(): - if key in LITELLM_SETTINGS_SAFE_DB_OVERRIDES: # params that are safe to override with db values - setattr(litellm, key, value) + if key in LITELLM_SETTINGS_SAFE_DB_OVERRIDES and (key != "max_budget" or value is not None): + setattr(litellm, key, float(value) if key == "max_budget" else value) # If param doesn't exist in config, add it if param_name not in current_config: diff --git a/tests/test_litellm/proxy/test_proxy_server.py b/tests/test_litellm/proxy/test_proxy_server.py index d9ac45c0531..a6faf31d795 100644 --- a/tests/test_litellm/proxy/test_proxy_server.py +++ b/tests/test_litellm/proxy/test_proxy_server.py @@ -9847,6 +9847,24 @@ def test_prompt_caching_settings_propagate_on_config_reload(monkeypatch, field_n assert getattr(litellm, field_name) == db_value +@pytest.mark.parametrize( + "db_value, expected_value", + [(10.0, 10.0), ("10.0", 10.0), (None, 0.00001)], +) +def test_max_budget_propagates_on_config_reload(monkeypatch, db_value, expected_value): + import litellm.proxy.proxy_server as ps + + monkeypatch.setattr(litellm, "max_budget", 0.00001) + + ps.ProxyConfig()._update_config_fields( + current_config={"litellm_settings": {"max_budget": 0.00001}}, + param_name="litellm_settings", + db_param_value={"max_budget": db_value}, + ) + + assert litellm.max_budget == expected_value + + def test_get_config_list_marks_untouched_prompt_caching_flag_as_not_set(monkeypatch): """The flag defaults to False rather than None, so a plain 'is not None' check would report the default as 'In Config' and imply an admin had set it."""