litellm - 💡(How to fix) Fix [Bug] team/member_update with max_budget_in_team=null leaves litellm_budget_table null, failing Pydantic validation on every subsequent request from that team's members

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…

POST /team/member_update accepts max_budget_in_team: null and clears the budget link on the underlying LiteLLM_TeamMembership row (both budget_id and the joined litellm_budget_table become null). The update returns HTTP 200 and /team/info reflects the cleared state. The DB schema permits this — litellm_budget_table is a nullable FK.

The LiteLLM_TeamMembership Pydantic model in v1.85+, however, treats litellm_budget_table as required (not Optional). Any subsequent request from a member of the affected team fails with:

1 validation error for LiteLLM_TeamMembership litellm_budget_table
  Field required [type=missing, input_value="REDACTED_BY_LITELLM", input_type=dict]
    For further information visit https://errors.pydantic.dev/2.12/v/missing

The error happens in the auth/load path on every request, so every virtual key belonging to a member of the affected team is bricked until the member budget is set back to a non-null value. This includes existing keys created before the membership was cleared.

Error Message

1 validation error for LiteLLM_TeamMembership litellm_budget_table The error happens in the auth/load path on every request, so every virtual key belonging to a member of the affected team is bricked until the member budget is set back to a non-null value. This includes existing keys created before the membership was cleared. All calls fail with the Pydantic validation error above. Every other team member is unaffected until their membership is also cleared.

Root Cause

POST /team/member_update accepts max_budget_in_team: null and clears the budget link on the underlying LiteLLM_TeamMembership row (both budget_id and the joined litellm_budget_table become null). The update returns HTTP 200 and /team/info reflects the cleared state. The DB schema permits this — litellm_budget_table is a nullable FK.

The LiteLLM_TeamMembership Pydantic model in v1.85+, however, treats litellm_budget_table as required (not Optional). Any subsequent request from a member of the affected team fails with:

1 validation error for LiteLLM_TeamMembership litellm_budget_table
  Field required [type=missing, input_value="REDACTED_BY_LITELLM", input_type=dict]
    For further information visit https://errors.pydantic.dev/2.12/v/missing

The error happens in the auth/load path on every request, so every virtual key belonging to a member of the affected team is bricked until the member budget is set back to a non-null value. This includes existing keys created before the membership was cleared.

Fix Action

Workaround

Set max_budget_in_team to a non-null value via /team/member_update. Setting it equal to the team's max_budget is functionally equivalent to "no per-member cap" since the team cap remains the binding constraint, while populating the field the Pydantic model requires.

Code Example

1 validation error for LiteLLM_TeamMembership litellm_budget_table
  Field required [type=missing, input_value="REDACTED_BY_LITELLM", input_type=dict]
    For further information visit https://errors.pydantic.dev/2.12/v/missing

---

curl -X POST $LITELLM/team/new \
  -H "Authorization: Bearer $MASTER_KEY" \
  -d '{"team_alias":"repro","max_budget":1000.0,"budget_duration":"30d"}'

---

curl -X POST $LITELLM/team/member_update \
  -H "Authorization: Bearer $MASTER_KEY" \
  -d '{"team_id":"<tid>","user_id":"alice","max_budget_in_team":50.0}'

---

curl -X POST $LITELLM/team/member_update \
  -H "Authorization: Bearer $MASTER_KEY" \
  -d '{"team_id":"<tid>","user_id":"alice","max_budget_in_team":null}'

---

curl -X POST $LITELLM/v1/chat/completions \
  -H "Authorization: Bearer <alice_key>" \
  -d '{"model":"some-model","messages":[{"role":"user","content":"hi"}]}'
RAW_BUFFERClick to expand / collapse

Description

POST /team/member_update accepts max_budget_in_team: null and clears the budget link on the underlying LiteLLM_TeamMembership row (both budget_id and the joined litellm_budget_table become null). The update returns HTTP 200 and /team/info reflects the cleared state. The DB schema permits this — litellm_budget_table is a nullable FK.

The LiteLLM_TeamMembership Pydantic model in v1.85+, however, treats litellm_budget_table as required (not Optional). Any subsequent request from a member of the affected team fails with:

1 validation error for LiteLLM_TeamMembership litellm_budget_table
  Field required [type=missing, input_value="REDACTED_BY_LITELLM", input_type=dict]
    For further information visit https://errors.pydantic.dev/2.12/v/missing

The error happens in the auth/load path on every request, so every virtual key belonging to a member of the affected team is bricked until the member budget is set back to a non-null value. This includes existing keys created before the membership was cleared.

Repro

  1. Create a team with a pool budget:
curl -X POST $LITELLM/team/new \
  -H "Authorization: Bearer $MASTER_KEY" \
  -d '{"team_alias":"repro","max_budget":1000.0,"budget_duration":"30d"}'
  1. Add a member with an explicit max_budget_in_team (this creates the LiteLLM_BudgetTable row and links it):
curl -X POST $LITELLM/team/member_update \
  -H "Authorization: Bearer $MASTER_KEY" \
  -d '{"team_id":"<tid>","user_id":"alice","max_budget_in_team":50.0}'
  1. Clear the member budget — semantically "alice has no per-member cap, only the team pool applies to her":
curl -X POST $LITELLM/team/member_update \
  -H "Authorization: Bearer $MASTER_KEY" \
  -d '{"team_id":"<tid>","user_id":"alice","max_budget_in_team":null}'

Returns 200. Verify via /team/info?team_id=<tid>: litellm_budget_table is null for alice's row.

  1. As alice, call any LLM endpoint with her virtual key:
curl -X POST $LITELLM/v1/chat/completions \
  -H "Authorization: Bearer <alice_key>" \
  -d '{"model":"some-model","messages":[{"role":"user","content":"hi"}]}'

All calls fail with the Pydantic validation error above. Every other team member is unaffected until their membership is also cleared.

Expected behavior

Either:

  • Treat null as the documented "no per-member cap" state — make litellm_budget_table: Optional[LiteLLM_BudgetTable] in the Pydantic model, OR
  • Reject the null write at the /team/member_update boundary with a 4xx that explains the schema constraint — don't accept a write that bricks future reads.

The current behavior is the worst of both: the write is silently accepted, the response and /team/info both show the cleared state, but every authenticated call from that user fails 5+ minutes later when the auth path tries to load the row.

Workaround

Set max_budget_in_team to a non-null value via /team/member_update. Setting it equal to the team's max_budget is functionally equivalent to "no per-member cap" since the team cap remains the binding constraint, while populating the field the Pydantic model requires.

Environment

  • LiteLLM v1.85.0 (also reproduced on v1.85.2)
  • Postgres 16 backend
  • Pydantic v2.12

Why we hit this

We were migrating away from a multi-layer per-key + per-member + team budget setup to a pool-only model (one team-level cap, no per-member or per-key ceilings) — exactly the use case the null value seems intended to support per the API surface.

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…

FAQ

Expected behavior

Either:

  • Treat null as the documented "no per-member cap" state — make litellm_budget_table: Optional[LiteLLM_BudgetTable] in the Pydantic model, OR
  • Reject the null write at the /team/member_update boundary with a 4xx that explains the schema constraint — don't accept a write that bricks future reads.

The current behavior is the worst of both: the write is silently accepted, the response and /team/info both show the cleared state, but every authenticated call from that user fails 5+ minutes later when the auth path tries to load the row.

Still need to ship something?

×6

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

Back to top recommendations

TRENDING