fix(proxy): json-encode team budget_limits on /team/new so Prisma accepts multi-window budgets - #31002
Conversation
…epts multi-window budgets
Greptile SummaryThis PR fixes a 500 error on
Confidence Score: 5/5The change is a one-liner serialization fix that aligns the create path with the update and key paths already doing the same thing; no new logic or control flow is introduced. The fix is minimal and targeted: it serializes a list field to a JSON string before a Prisma write, exactly matching what the update path has done for the same column. The jsonify_object bypass for lists is confirmed in the source, _to_model correctly json-decodes strings on read, and the regression test covers the failure scenario end-to-end with proper mocking. No files require special attention.
|
| Filename | Overview |
|---|---|
| litellm/proxy/management_endpoints/team_endpoints.py | Adds json.dumps serialization for budget_limits before the Prisma create call, mirroring the existing router_settings and members_with_roles patterns; the placement (after model_dump, before jsonify_team_object) is correct and safe against double-encoding. |
| tests/test_litellm/proxy/management_endpoints/test_team_endpoints.py | Adds a regression test that correctly mocks the DB layer (including overriding jsonify_team_object to identity), runs new_team, and asserts budget_limits is stored as a JSON string with both windows and populated reset_at fields; no real network calls made. |
Reviews (1): Last reviewed commit: "fix(proxy): json-encode team budget_limi..." | Re-trigger Greptile
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
|
Superseded by in-repo PR #31019 (pushed to BerriAI/litellm directly so full CI runs; cross-fork PRs skip the secret-gated jobs). |
Relevant issues
POST /team/newreturns a 500 when the request includes multi-windowbudget_limits. Prisma rejects the create with:The root cause is that the create path builds
complete_team_data_dict = complete_team_data.model_dump(exclude_none=True)and hands it to the team-create call. That dict flows throughjsonify_team_object->jsonify_object, which onlyjson.dumpsvalues that are adict.budget_limitsis alist, so it passes through unencoded and Prisma refuses it because theLiteLLM_TeamTable.budget_limitscolumn isJson?. The update path already serializes it viajson.dumpsand the key path does the same, so this aligns/team/newwith the rest of the codebase.The fix json-encodes
budget_limitson the dict right aftermodel_dump, parallel to the existingrouter_settingsserialization just below it. This is safe against double-encoding:jsonify_objectleaves strings alone,TeamRepository._to_modeljson-loads when the value is a string,proxy_serverhandles the string case on read, and the reset-budget job tolerates both a list and a json string.Linear ticket
LIT-3896
Pre-Submission checklist
make test-unit@greptileaiand received a Confidence Score of at least 4/5 before requesting a maintainer reviewCI (LiteLLM team)
Branch creation CI run
Link:
CI run for the last commit
Link:
Merge / cherry-pick CI run
Links:
Screenshots / Proof of Fix
Run a local proxy, then create a team with two budget windows and read it back. Before this change the create returns a 500; after it, the create returns 200 with a
team_idandGET /team/infoshows both windows persisted with a populatedreset_at.Type
🐛 Bug Fix
Changes
new_teamnow serializesbudget_limitswithjson.dumpson the create payload so theJson?column accepts the value, matching how the update and key paths already handle it. Added a regression testtest_new_team_serializes_multi_window_budget_limitsthat builds aNewTeamRequestwith two windows, runsnew_teamwith admin auth, captures the data passed tolitellm_teamtable.create, and asserts the storedbudget_limitsis a json string that decodes to a list carrying both windows plus a populatedreset_at. The test fails before the fix (the value is a raw list) and passes after