mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-13 23:11:40 +00:00
fix(proxy): reset user budget to unlimited by clearing blank budget_duration
Fixes #32474
This commit is contained in:
parent
bfff5e8d86
commit
59784062c1
2 changed files with 38 additions and 3 deletions
|
|
@ -1090,9 +1090,12 @@ def _update_internal_user_params(
|
|||
if "budget_duration" in non_default_values:
|
||||
from litellm.proxy.common_utils.timezone_utils import get_budget_reset_time
|
||||
|
||||
non_default_values["budget_reset_at"] = get_budget_reset_time(
|
||||
budget_duration=non_default_values["budget_duration"]
|
||||
)
|
||||
budget_duration = non_default_values["budget_duration"]
|
||||
if isinstance(budget_duration, str) and not budget_duration.strip():
|
||||
non_default_values["budget_duration"] = None
|
||||
non_default_values["budget_reset_at"] = None
|
||||
else:
|
||||
non_default_values["budget_reset_at"] = get_budget_reset_time(budget_duration=budget_duration)
|
||||
|
||||
if "max_budget" not in non_default_values:
|
||||
if (
|
||||
|
|
|
|||
|
|
@ -1979,6 +1979,38 @@ def test_update_internal_user_params_reset_max_budget_with_none():
|
|||
assert non_default_values["user_id"] == "test_user"
|
||||
|
||||
|
||||
def test_update_internal_user_params_blank_budget_duration_clears_reset():
|
||||
"""
|
||||
Relevant Issue: https://github.com/BerriAI/litellm/issues/32474
|
||||
|
||||
A blank budget_duration (empty or whitespace-only string) means "no reset"
|
||||
(unlimited). It must be persisted as NULL with budget_reset_at cleared,
|
||||
instead of an unparseable empty string that later crashes duration parsing
|
||||
with "Invalid duration format".
|
||||
"""
|
||||
from litellm.litellm_core_utils.duration_parser import duration_in_seconds
|
||||
|
||||
for blank in ("", " "):
|
||||
data = UpdateUserRequest(user_id="test_user", max_budget=None, budget_duration=blank)
|
||||
non_default_values = _update_internal_user_params(
|
||||
data_json=data.model_dump(exclude_unset=True), data=data
|
||||
)
|
||||
|
||||
assert non_default_values["budget_duration"] is None
|
||||
assert non_default_values["budget_reset_at"] is None
|
||||
assert non_default_values["max_budget"] is None
|
||||
|
||||
# A real duration is still honored and produces a reset time
|
||||
data = UpdateUserRequest(user_id="test_user", budget_duration="30d")
|
||||
non_default_values = _update_internal_user_params(data_json=data.model_dump(exclude_unset=True), data=data)
|
||||
assert non_default_values["budget_duration"] == "30d"
|
||||
assert non_default_values["budget_reset_at"] is not None
|
||||
|
||||
# Guard the regression: an empty duration must never reach duration_in_seconds
|
||||
with pytest.raises(ValueError):
|
||||
duration_in_seconds("")
|
||||
|
||||
|
||||
def test_update_internal_user_params_ignores_other_nones():
|
||||
"""
|
||||
Test that other fields are still filtered out if None
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue