diff --git a/litellm/proxy/common_utils/reset_budget_job.py b/litellm/proxy/common_utils/reset_budget_job.py index ef4c87c2ed4..a983599e532 100644 --- a/litellm/proxy/common_utils/reset_budget_job.py +++ b/litellm/proxy/common_utils/reset_budget_job.py @@ -390,8 +390,8 @@ async def _write_team_windows(prisma_client: PrismaClient, row_id: str, payload: async def _write_user_windows(prisma_client: PrismaClient, row_id: str, payload: str) -> None: await UserRepository(prisma_client).table.update( - where={"user_id": row_id}, - data={"budget_limits": payload}, + where={"user_id": row_id}, # mutable-ok: prisma where filter must be a dict + data={"budget_limits": payload}, # mutable-ok: prisma update payload must be a dict ) diff --git a/litellm/proxy/management_endpoints/common_utils.py b/litellm/proxy/management_endpoints/common_utils.py index b03a48a596e..36f7464c8bb 100644 --- a/litellm/proxy/management_endpoints/common_utils.py +++ b/litellm/proxy/management_endpoints/common_utils.py @@ -59,11 +59,14 @@ def validate_budget_limits(budget_limits: Sequence[object] | None, status_code: for window in windows: error: Final = budget_duration_error(window.budget_duration) if error is not None: - raise HTTPException(status_code=status_code, detail={"error": error}) + raise HTTPException( + status_code=status_code, + detail={"error": error}, # mutable-ok: HTTPException detail must be a dict + ) if not math.isfinite(window.max_budget) or window.max_budget <= 0: raise HTTPException( status_code=status_code, - detail={ + detail={ # mutable-ok: HTTPException detail must be a dict "error": f"budget_limits entry max_budget ({window.max_budget}) must be a positive finite number." }, ) @@ -72,7 +75,9 @@ def validate_budget_limits(budget_limits: Sequence[object] | None, status_code: if duplicate is not None: raise HTTPException( status_code=status_code, - detail={"error": f"budget_limits has a duplicate budget_duration '{duplicate}'."}, + detail={ # mutable-ok: HTTPException.detail has no immutable form + "error": f"budget_limits has a duplicate budget_duration '{duplicate}'." + }, ) diff --git a/litellm/proxy/management_endpoints/internal_user_endpoints.py b/litellm/proxy/management_endpoints/internal_user_endpoints.py index 7bd95f9a417..0061a8e5733 100644 --- a/litellm/proxy/management_endpoints/internal_user_endpoints.py +++ b/litellm/proxy/management_endpoints/internal_user_endpoints.py @@ -1256,11 +1256,16 @@ def _prepare_user_budget_limits(value: object) -> str: if not value: return json.dumps(None) - initialized_windows: Final = [] - for window in cast(Sequence[object], value): - w = window if isinstance(window, dict) else window.model_dump() # pyright: ignore[reportAttributeAccessIssue] # BudgetLimitEntry or its JSON dict - w["reset_at"] = get_budget_reset_time(budget_duration=w["budget_duration"]).isoformat() - initialized_windows.append(w) + initialized_windows: Final = tuple( + { # mutable-ok: prisma stores a dict row per budget window + **w, + "reset_at": get_budget_reset_time(budget_duration=w["budget_duration"]).isoformat(), + } + for w in ( + window if isinstance(window, dict) else window.model_dump() # pyright: ignore[reportAttributeAccessIssue] # BudgetLimitEntry or its JSON dict + for window in cast(Sequence[object], value) + ) + ) return json.dumps(initialized_windows) diff --git a/ui/litellm-dashboard/src/components/team/TeamInfo.tsx b/ui/litellm-dashboard/src/components/team/TeamInfo.tsx index 437200fc0da..e198059bacd 100644 --- a/ui/litellm-dashboard/src/components/team/TeamInfo.tsx +++ b/ui/litellm-dashboard/src/components/team/TeamInfo.tsx @@ -1001,9 +1001,9 @@ const TeamInfoView: React.FC = ({ .map((w) => `${w.budget_duration}:${w.max_budget}`) .sort() .join("|"); - const validWindows = (values.budget_limits ?? []).filter( - (w) => w.budget_duration && w.max_budget !== null && w.max_budget !== undefined, - ); + const validWindows = ( + (values.budget_limits ?? []) as { budget_duration: string; max_budget: number | null }[] + ).filter((w) => w.budget_duration && w.max_budget !== null && w.max_budget !== undefined); if (windowSignature(info.budget_limits) !== windowSignature(validWindows)) { updateData.budget_limits = validWindows; }