Skip to content

fix(ui): keep team role and budget when the team ID is blank#34608

Open
yuneng-berri wants to merge 1 commit into
litellm_internal_stagingfrom
litellm_/nifty-hopper-a7325e
Open

fix(ui): keep team role and budget when the team ID is blank#34608
yuneng-berri wants to merge 1 commit into
litellm_internal_stagingfrom
litellm_/nifty-hopper-a7325e

Conversation

@yuneng-berri

Copy link
Copy Markdown
Collaborator

TLDR

Problem this solves:

  • Team role/budget silently reset when the team ID is blank
  • Editing a second field on that row drops the first

How it solves it:

  • Guard the object branch on shape, not on a truthy team_id
  • Regression tests pin the display and the save payload

Relevant issues

Linear ticket

Pre-Submission checklist

Please complete all items before asking a LiteLLM maintainer to review your PR

  • I have added meaningful tests
  • My PR passes all CI/CD checks (e.g., lint, format, unit tests)
  • My PR's scope is as isolated as possible; it only solves 1 specific problem
  • I have received a Greptile Confidence Score of at least 4/5 before requesting a maintainer review (Greptile reviews automatically once the PR is opened; only comment @greptileai to re-request a review after pushing changes)

Delays in PR merge?

If you're seeing a delay in your PR being merged, ping the LiteLLM Team on Slack (#pr-review).

Screenshots / Proof of Fix

Steps to reproduce by hand, with the Admin UI dev server on :3000 pointed at a proxy on :4000:

  1. Go to http://localhost:3000/?page=users and open the "Default User Settings" tab
  2. Click "Edit Settings", then "Add Team"
  3. Leave "Team ID" empty and change "User Role" to Admin

Before (b9b27c2): the dropdown snaps back to "User" as soon as it re-renders

After (7a718d1): the dropdown stays on Admin

  1. Still leaving "Team ID" empty, type 25 into "Max Budget in Team", then set "User Role" to Admin

Before (b9b27c2): the budget you just typed is gone from the row

After (7a718d1): both the budget and the role survive, and "Save Changes" sends them

Type

🐛 Bug Fix

Changes

normalizeTeams guarded its object branch on the truthiness of team.team_id, so any entry whose ID is an empty string fell through to the branch that returns a bare { team_id: "", user_role: "user" }, discarding user_role and max_budget_in_team

That normalized copy feeds both the rendered row and updateTeam, which is why the symptom shows up twice: the role dropdown re-renders as "User" even though the edited value holds "admin", and because updateTeam spreads the normalized copy, the next edit to that row also wipes whatever was set before it. It bites on load too, since a team saved with a blank ID comes back with its role reset

The guard now tests the shape of the entry (typeof team === "object" && team !== null && "team_id" in team) instead of the value, so a blank ID keeps its siblings. The bug predates the shadcn migration of this component and is unrelated to it

Three tests in the mapped DefaultUserSettings.test.tsx cover it: the role stays selected with a blank ID, a stored team with a blank ID keeps its role and budget on load, and the save payload carries both fields after two sequential edits. Reverting the guard fails all three; dropping max_budget_in_team or the user_role fallback each fails two

Final Attestation

  • The tests check the right things, including the edge cases, and regressions in the respective real-world customer use-cases are not possible after this PR

normalizeTeams guarded the object branch on the truthiness of team.team_id,
so a row with an empty ID fell through to the reset branch that discards
user_role and max_budget_in_team. Setting a role before typing an ID showed
the row snapping back to "user", and the next edit to that row dropped
whatever had been set before it. Guard on the shape of the entry instead.
@greptile-apps

greptile-apps Bot commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR updates team normalization to preserve role and budget fields when a team has a blank ID

  • Uses object shape rather than team_id truthiness to select the structured-team branch
  • Adds regression coverage for rendering stored values, retaining edits, and submitting the save payload

Confidence Score: 5/5

The PR appears safe to merge with no actionable defects identified

The revised guard handles the supported string and structured-object team representations correctly, and the added tests exercise both loaded settings and sequential edits before saving

Important Files Changed

Filename Overview
ui/litellm-dashboard/src/app/(dashboard)/users/_components/DefaultUserSettings.tsx The normalization guard correctly recognizes structured team entries with blank IDs while retaining their role and budget
ui/litellm-dashboard/src/app/(dashboard)/users/_components/DefaultUserSettings.test.tsx Focused regression tests cover initial display, role retention, sequential edits, and the resulting save payload

Reviews (1): Last reviewed commit: "fix(ui): keep team role and budget when ..." | Re-trigger Greptile

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant