Skip to content

fix(proxy): json-encode team budget_limits on /team/new so Prisma accepts multi-window budgets - #31019

Closed
mubashir1osmani wants to merge 1 commit into
litellm_internal_stagingfrom
litellm_team_new_budget_limits_json_encode
Closed

fix(proxy): json-encode team budget_limits on /team/new so Prisma accepts multi-window budgets#31019
mubashir1osmani wants to merge 1 commit into
litellm_internal_stagingfrom
litellm_team_new_budget_limits_json_encode

Conversation

@mubashir1osmani

Copy link
Copy Markdown
Collaborator

Relevant issues

POST /team/new returns a 500 when the request includes multi-window budget_limits. Prisma rejects the create with:

Unable to match input value to any allowed input type for the field.
Parse errors: [Invalid argument type. `budget_limits` should be of any of the following types: `NullableJsonNullValueInput`, `Json`]

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 through jsonify_team_object -> jsonify_object, which only json.dumps values that are a dict. budget_limits is a list, so it passes through unencoded and Prisma refuses it because the LiteLLM_TeamTable.budget_limits column is Json?. The update path already serializes it via json.dumps and the key path does the same, so this aligns /team/new with the rest of the codebase.

The fix json-encodes budget_limits on the dict right after model_dump, parallel to the existing router_settings serialization just below it. This is safe against double-encoding: jsonify_object leaves strings alone, TeamRepository._to_model json-loads when the value is a string, proxy_server handles 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

  • I have added meaningful tests
  • My PR passes all unit tests on make test-unit
  • My PR's scope is as isolated as possible; it only solves 1 specific problem
  • I have requested a Greptile review by commenting @greptileai and received a Confidence Score of at least 4/5 before requesting a maintainer review

CI (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_id and GET /team/info shows both windows persisted with a populated reset_at.

# 1. start the proxy (separate terminal)
python litellm/proxy/proxy_cli.py --config litellm/proxy/dev_config.yaml --detailed_debug --reload --use_v2_migration_resolver 2>&1 | tee litellm.log

# 2. create a team with two budget windows
TEAM_ID=$(curl -s -X POST http://localhost:4000/team/new \
  -H "Authorization: Bearer sk-1234" \
  -H "Content-Type: application/json" \
  -d '{
        "team_alias": "multi-window-team",
        "budget_limits": [
          {"budget_duration": "1d",  "max_budget": 10.0},
          {"budget_duration": "30d", "max_budget": 100.0}
        ]
      }' | tee /dev/stderr | python -c "import sys, json; print(json.load(sys.stdin)['team_id'])")

# 3. read it back and confirm both windows persisted with reset_at
curl -s "http://localhost:4000/team/info?team_id=$TEAM_ID" \
  -H "Authorization: Bearer sk-1234" | python -m json.tool

Type

🐛 Bug Fix

Changes

new_team now serializes budget_limits with json.dumps on the create payload so the Json? column accepts the value, matching how the update and key paths already handle it. Added a regression test test_new_team_serializes_multi_window_budget_limits that builds a NewTeamRequest with two windows, runs new_team with admin auth, captures the data passed to litellm_teamtable.create, and asserts the stored budget_limits is a json string that decodes to a list carrying both windows plus a populated reset_at. The test fails before the fix (the value is a raw list) and passes after

@greptile-apps

greptile-apps Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes a 500 error on POST /team/new when budget_limits is provided as a multi-window list. The root cause was that jsonify_object only JSON-encodes dict values, leaving a Python list unencoded so Prisma rejects it for the Json? column.

  • team_endpoints.py: Adds a json.dumps call on budget_limits immediately after model_dump, mirroring the identical serialization already present in the update path (line 2065) and in the key-creation path.
  • test_team_endpoints.py: Adds a mock-only regression test (test_new_team_serializes_multi_window_budget_limits) that intercepts the Prisma create call and asserts budget_limits is a JSON string that decodes to a list of two windows with populated reset_at values.

Confidence Score: 5/5

Safe to merge — a minimal, targeted one-function change that aligns the create path with the already-working update path.

The fix is a direct analog of the serialization already on line 2065 for the update path. No double-encoding risk exists because jsonify_object only re-encodes dict values and a string passes through unchanged, and _to_model already json.loads string-valued JSON fields on read. The regression test is mock-only, exercises the exact code path, and would fail without the fix.

No files require special attention.

Important Files Changed

Filename Overview
litellm/proxy/management_endpoints/team_endpoints.py Adds a 5-line json.dumps call for budget_limits right after model_dump, mirroring the existing serialization at line 2065 in the update path and fixing the Prisma 500.
tests/test_litellm/proxy/management_endpoints/test_team_endpoints.py Adds a focused regression test that intercepts the Prisma create call and verifies budget_limits is a JSON string containing both windows with populated reset_at; uses only mocks, no real network calls.

Reviews (1): Last reviewed commit: "fix(proxy): json-encode team budget_limi..." | Re-trigger Greptile

@mubashir1osmani

Copy link
Copy Markdown
Collaborator Author

duplicate of #31045

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