litellm - ✅(Solved) Fix [Bug]: /team/member_update always creates new budget rows, orphaning previous ones [1 pull requests, 1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
BerriAI/litellm#25508Fetched 2026-04-11 06:13:43
View on GitHub
Comments
0
Participants
1
Timeline
2
Reactions
0
Participants
Timeline (top)
labeled ×2

PR fix notes

PR #25609: fix(proxy): update existing budget row in /team/member_update instead of creating new

Description (problem / solution / changelog)

Summary

  • _upsert_budget_and_membership accepted existing_budget_id but always created a new budget row, orphaning the previous one
  • Now when existing_budget_id is provided, the function updates the existing row in-place via litellm_budgettable.update()
  • Only creates a new row + links membership when no prior budget exists

Test plan

  • Updated 6 tests in test_upsert_budget_membership.py to verify:
    • Disconnect path (all limits None)
    • Update existing budget in-place when existing_budget_id is provided
    • Create new budget + link membership when no existing budget
    • Create then update flow (two sequential calls)
    • RPM/TPM limit updates on existing budget
    • RPM-only create with no existing budget
  • All tests pass locally
  • Black formatting applied

Closes #25508

Changed files

  • litellm/proxy/management_endpoints/common_utils.py (modified, +51/-36)
  • tests/test_litellm/proxy/common_utils/test_upsert_budget_membership.py (modified, +48/-93)

Code Example

curl -X POST http://localhost:4000/team/update \
     -H "Authorization: Bearer sk-admin" \
     -H "Content-Type: application/json" \
     -d '{"team_id": "1", "team_member_budget": 2.0, "team_member_budget_duration": "30d"}'

   curl -X POST http://localhost:4000/team/member_add \
     -H "Authorization: Bearer sk-admin" \
     -H "Content-Type: application/json" \
     -d '{"team_id": "1", "member": {"user_id": "user-A", "role": "user"}}'

---

curl -X POST http://localhost:4000/team/member_update \
     -H "Authorization: Bearer sk-admin" \
     -H "Content-Type: application/json" \
     -d '{"team_id": "1", "user_id": "user-A", "max_budget_in_team": 5}'

---

No relevant log files. Maybe a JSON representation of /team/info helps with understanding.

# Before member_update
{ "user_id": "user-A", "budget_id": "team-budget-abc", "litellm_budget_table": { "max_budget": 2.0 } }

# After first member_update
{ "user_id": "user-A", "budget_id": "59db2fc6-...", "litellm_budget_table": { "max_budget": 5.0 } }
# budget row "team-budget-abc" still exists in DB (orphaned if no other members reference it)

# After second member_update
{ "user_id": "user-A", "budget_id": "a1b2c3d4-...", "litellm_budget_table": { "max_budget": 8.0 } }
# budget rows "team-budget-abc" AND "59db2fc6-..." now both orphaned
RAW_BUFFERClick to expand / collapse

Check for existing issues

  • I have searched the existing issues and checked that my issue is not a duplicate.

What happened?

When calling /team/member_update with max_budget_in_team, the _upsert_budget_and_membership function always creates a new budget row via litellm_budgettable.create. The member's team_membership is then connected to the new budget. However, the previous budget row is never deleted, leaving orphaned rows in litellm_budgettable.

Creating a new individual budget when explicitly overriding a member's value is correct, it properly detaches them from a shared budget. The issue is purely that the old budget row is left behind.

Repeatedly calling member_update for the same member (e.g., adjusting their budget multiple times) creates a new orphaned row each time.

Expected behavior: The previous budget row should be cleaned up (deleted) when a new one is created and linked, unless it is still referenced by other memberships.

Actual behavior: Old budget rows accumulate in litellm_budgettable with no references.

Steps to Reproduce

  1. Create a team with a member budget and add a member:
    curl -X POST http://localhost:4000/team/update \
      -H "Authorization: Bearer sk-admin" \
      -H "Content-Type: application/json" \
      -d '{"team_id": "1", "team_member_budget": 2.0, "team_member_budget_duration": "30d"}'
    
    curl -X POST http://localhost:4000/team/member_add \
      -H "Authorization: Bearer sk-admin" \
      -H "Content-Type: application/json" \
      -d '{"team_id": "1", "member": {"user_id": "user-A", "role": "user"}}'
  2. Note the member's budget_id from GET /team/info?team_id=1 (e.g., team-...-budget-abc)
  3. Update the member's budget:
    curl -X POST http://localhost:4000/team/member_update \
      -H "Authorization: Bearer sk-admin" \
      -H "Content-Type: application/json" \
      -d '{"team_id": "1", "user_id": "user-A", "max_budget_in_team": 5}'
  4. Note the member now has a new budget_id (e.g., 59db2fc6-...). The old budget row (team-...-budget-abc) still exists in litellm_budgettable but is no longer referenced by this member.
  5. Repeat step 3 multiple times, each call creates another orphaned budget row.

Relevant log output

No relevant log files. Maybe a JSON representation of /team/info helps with understanding.

# Before member_update
{ "user_id": "user-A", "budget_id": "team-budget-abc", "litellm_budget_table": { "max_budget": 2.0 } }

# After first member_update
{ "user_id": "user-A", "budget_id": "59db2fc6-...", "litellm_budget_table": { "max_budget": 5.0 } }
# budget row "team-budget-abc" still exists in DB (orphaned if no other members reference it)

# After second member_update
{ "user_id": "user-A", "budget_id": "a1b2c3d4-...", "litellm_budget_table": { "max_budget": 8.0 } }
# budget rows "team-budget-abc" AND "59db2fc6-..." now both orphaned

What part of LiteLLM is this about?

Proxy

What LiteLLM version are you on ?

v1.83.3.rc.1

Twitter / LinkedIn details

No response

extent analysis

TL;DR

Delete the previous budget row from litellm_budgettable when a new budget is created and linked to a member, unless it is still referenced by other memberships.

Guidance

  • Identify the previous budget row in the _upsert_budget_and_membership function before creating a new one and check if it has any other references.
  • If the previous budget row has no other references, delete it after creating the new budget row.
  • Modify the member_update endpoint to handle the deletion of the previous budget row.
  • Verify the fix by checking the litellm_budgettable for orphaned rows after updating a member's budget multiple times.

Example

# Pseudo-code example of the _upsert_budget_and_membership function
def _upsert_budget_and_membership(member_id, new_budget):
    # Get the previous budget row
    previous_budget_row = get_previous_budget_row(member_id)
    
    # Create a new budget row
    new_budget_row = litellm_budgettable.create(new_budget)
    
    # Check if the previous budget row has any other references
    if not has_other_references(previous_budget_row):
        # Delete the previous budget row
        delete_budget_row(previous_budget_row)
    
    # Link the new budget row to the member
    link_budget_to_member(member_id, new_budget_row)

Notes

This fix assumes that the litellm_budgettable has a way to check for other references to a budget row. The actual implementation may vary depending on the database schema and the logic of the _upsert_budget_and_membership function.

Recommendation

Apply a workaround to delete the previous budget row when a new one is created, unless it is still referenced by other memberships, to prevent orphaned rows in litellm_budgettable. This will ensure data consistency and prevent unnecessary data accumulation.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

litellm - ✅(Solved) Fix [Bug]: /team/member_update always creates new budget rows, orphaning previous ones [1 pull requests, 1 participants]