From 497f6ca5568c88488a0427cc79e95bbf2caf9ad1 Mon Sep 17 00:00:00 2001 From: Yuneng Jiang Date: Mon, 22 Jun 2026 18:38:15 -0700 Subject: [PATCH] fix(proxy): serialize team budget_limits to JSON in jsonify_team_object POST /team/new with any budget_limits returned 500 because jsonify_team_object serialized members_with_roles but left budget_limits as a raw Python list, which Prisma's Json column rejects. /team/update and /key/generate worked only because each json.dumps the windows itself. Serialize budget_limits in the shared helper, guarded by isinstance(list) so the pre-serialized /team/update path is unaffected. --- litellm/proxy/utils.py | 4 +++ .../test_prisma_client_get_data.py | 27 +++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/litellm/proxy/utils.py b/litellm/proxy/utils.py index ea8ab2f9b8e4..755602cbcc0e 100644 --- a/litellm/proxy/utils.py +++ b/litellm/proxy/utils.py @@ -3792,6 +3792,10 @@ def jsonify_team_object(self, db_data: dict): db_data["members_with_roles"], list ): db_data["members_with_roles"] = json.dumps(db_data["members_with_roles"]) + if db_data.get("budget_limits", None) is not None and isinstance( + db_data["budget_limits"], list + ): + db_data["budget_limits"] = json.dumps(db_data["budget_limits"]) return db_data # Define a retrying strategy with exponential backoff diff --git a/tests/test_litellm/proxy/utils/prisma_and_spend/test_prisma_client_get_data.py b/tests/test_litellm/proxy/utils/prisma_and_spend/test_prisma_client_get_data.py index d517c1c346f0..87063bdf00b3 100644 --- a/tests/test_litellm/proxy/utils/prisma_and_spend/test_prisma_client_get_data.py +++ b/tests/test_litellm/proxy/utils/prisma_and_spend/test_prisma_client_get_data.py @@ -105,6 +105,33 @@ def test_jsonify_team_object_converts_members_to_json_string( } +def test_jsonify_team_object_converts_budget_limits_to_json_string( + prisma_client: PrismaClient, +) -> None: + data = { + "team_id": "t1", + "budget_limits": [ + { + "budget_duration": "1d", + "max_budget": 10.0, + "reset_at": "2026-01-01T00:00:00Z", + }, + { + "budget_duration": "7d", + "max_budget": 50.0, + "reset_at": "2026-01-07T00:00:00Z", + }, + ], + "models": ["gpt-4"], + } + result = prisma_client.jsonify_team_object(data) + assert result == { + "team_id": "t1", + "budget_limits": json.dumps(data["budget_limits"]), + "models": ["gpt-4"], + } + + def test_jsonify_team_object_error_on_non_dict(prisma_client: PrismaClient) -> None: with pytest.raises(AttributeError): prisma_client.jsonify_team_object(None) # type: ignore[arg-type]