fix(ui): use sanitizeNumeric for team_member_budget in team edit form (#23505)

* fix(gemini): preserve toolConfig on native generate_content (#23493)

* fix(ui): use sanitizeNumeric for team_member_budget in team edit form

The team edit form (TeamInfo.tsx) used Number() to convert the
team_member_budget field value, which silently converts null/undefined/""
to 0. When an admin edits a team for any reason without touching the
budget field, this sends team_member_budget=0 to the backend, creating a
shared budget row with max_budget=0.0 that blocks all team members.

Use sanitizeNumeric (already used for tpm_limit, rpm_limit, soft_budget
in the same form) which correctly returns null for empty/null/undefined
values, preventing accidental zero-budget creation.

---------

Co-authored-by: Emerson Gomes <emerson.gomes@thalesgroup.com>
This commit is contained in:
michelligabriele 2026-03-13 20:06:36 +01:00 committed by GitHub
parent 43db397854
commit 239edc472a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 60 additions and 1 deletions

View file

@ -1385,6 +1385,65 @@ async def test_update_team_team_member_budget_not_passed_to_db():
)
def test_should_create_budget_with_none_values():
"""Test that should_create_budget returns False when all values are None."""
from litellm.proxy.management_endpoints.team_endpoints import (
TeamMemberBudgetHandler,
)
assert TeamMemberBudgetHandler.should_create_budget() is False
assert (
TeamMemberBudgetHandler.should_create_budget(
team_member_budget=None,
team_member_rpm_limit=None,
team_member_tpm_limit=None,
team_member_budget_duration=None,
)
is False
)
def test_should_create_budget_with_zero_budget():
"""Test that should_create_budget returns True for explicit 0 budget.
0 is a valid explicit budget (zero dollars allowed). The UI bug was
sending 0 when the user didn't set a value — that's fixed in the UI
by using sanitizeNumeric. The backend correctly treats 0 as intentional.
"""
from litellm.proxy.management_endpoints.team_endpoints import (
TeamMemberBudgetHandler,
)
assert TeamMemberBudgetHandler.should_create_budget(team_member_budget=0) is True
assert (
TeamMemberBudgetHandler.should_create_budget(team_member_budget=0.0) is True
)
def test_should_create_budget_with_valid_values():
"""Test that should_create_budget returns True when any value is provided."""
from litellm.proxy.management_endpoints.team_endpoints import (
TeamMemberBudgetHandler,
)
assert (
TeamMemberBudgetHandler.should_create_budget(team_member_budget=100.0) is True
)
assert (
TeamMemberBudgetHandler.should_create_budget(team_member_rpm_limit=50) is True
)
assert (
TeamMemberBudgetHandler.should_create_budget(team_member_tpm_limit=1000)
is True
)
assert (
TeamMemberBudgetHandler.should_create_budget(
team_member_budget_duration="30d"
)
is True
)
def test_clean_team_member_fields():
"""
Test that _clean_team_member_fields removes all team member fields from a dictionary.

View file

@ -497,7 +497,7 @@ const TeamInfoView: React.FC<TeamInfoProps> = ({
updateData.team_member_budget_duration = values.team_member_budget_duration;
if (values.team_member_budget !== undefined) {
updateData.team_member_budget = Number(values.team_member_budget);
updateData.team_member_budget = sanitizeNumeric(values.team_member_budget);
}
if (values.team_member_key_duration !== undefined) {