From 0d4934d7e666a6f0848870415f1d17fbda5d2f73 Mon Sep 17 00:00:00 2001 From: Karlla Nascimento <89461448+karllasnascimento@users.noreply.github.com> Date: Sun, 29 Mar 2026 16:56:08 -0300 Subject: [PATCH] fix: deep copy kwargs in run_async_fallback to prevent mutation The router reuses the same kwargs dict across fallback attempts. Provider-specific transformations (e.g., Bedrock converse_handler.py popping 'tools' from optional_params) mutate kwargs in-place, corrupting them for subsequent fallback providers. This adds safe_deep_copy(kwargs) before each fallback attempt, following the same pattern used in fallback_utils.py. Fixes: https://github.com/BerriAI/litellm/issues/24764 --- litellm/router_utils/fallback_event_handlers.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/litellm/router_utils/fallback_event_handlers.py b/litellm/router_utils/fallback_event_handlers.py index 62e706a0cf5..2130e10e38f 100644 --- a/litellm/router_utils/fallback_event_handlers.py +++ b/litellm/router_utils/fallback_event_handlers.py @@ -8,6 +8,7 @@ from litellm.router_utils.add_retry_fallback_headers import ( add_fallback_headers_to_response, ) from litellm.types.router import LiteLLMParamsTypedDict +from litellm.litellm_core_utils.core_helpers import safe_deep_copy if TYPE_CHECKING: from litellm.router import Router as _Router @@ -123,7 +124,13 @@ async def run_async_fallback( if mg == original_model_group: continue try: - # LOGGING + # Deep copy kwargs to prevent mutations from one provider + # (e.g., Bedrock popping 'tools' from optional_params) + # from corrupting kwargs for subsequent fallback providers. + # See: https://github.com/BerriAI/litellm/issues/24764 + kwargs = safe_deep_copy(kwargs) + + # LOGGING kwargs = litellm_router.log_retry(kwargs=kwargs, e=original_exception) verbose_router_logger.info(f"Falling back to model_group = {mg}") if isinstance(mg, str):