From 2df755425a8401c47ac31fec9f2e296120d67f70 Mon Sep 17 00:00:00 2001 From: zach Date: Fri, 10 Apr 2026 22:25:46 -0700 Subject: [PATCH] fix: replace mutable default arguments (= [] and = {}) with None Mutable default arguments in Python are shared across all calls, causing subtle state-leak bugs. Replaced with Optional[...] = None and initialized inside the function body. Affected: - utils.decode(): tokens: List[int] = [] -> Optional[List[int]] = None - VectorStoreRegistry.__init__(): vector_stores = [] -> None - get_litellm_model_info(): model: dict = {} -> Optional[dict] = None - LowestCostLoggingHandler.__init__(): routing_args = {} -> None - LowestLatencyLoggingHandler.__init__(): routing_args = {} -> None - LowestTPM_RPM_Routing.__init__(): routing_args = {} -> None - LowestTPM_RPM_Routing_v2.__init__(): routing_args = {} -> None --- litellm/proxy/proxy_server.py | 4 +++- litellm/router_strategy/lowest_cost.py | 2 +- litellm/router_strategy/lowest_latency.py | 4 +++- litellm/router_strategy/lowest_tpm_rpm.py | 4 +++- litellm/router_strategy/lowest_tpm_rpm_v2.py | 4 +++- litellm/utils.py | 4 +++- litellm/vector_stores/vector_store_registry.py | 4 ++-- 7 files changed, 18 insertions(+), 8 deletions(-) diff --git a/litellm/proxy/proxy_server.py b/litellm/proxy/proxy_server.py index 85a12f70f58..44badc80c2d 100644 --- a/litellm/proxy/proxy_server.py +++ b/litellm/proxy/proxy_server.py @@ -5954,7 +5954,9 @@ def select_data_generator( ) -def get_litellm_model_info(model: dict = {}): +def get_litellm_model_info(model: Optional[dict] = None): + if model is None: + model = {} model_info = model.get("model_info", {}) model_to_lookup = model.get("litellm_params", {}).get("model", None) try: diff --git a/litellm/router_strategy/lowest_cost.py b/litellm/router_strategy/lowest_cost.py index 54498363f51..46f1fc8bc7b 100644 --- a/litellm/router_strategy/lowest_cost.py +++ b/litellm/router_strategy/lowest_cost.py @@ -15,7 +15,7 @@ class LowestCostLoggingHandler(CustomLogger): logged_success: int = 0 logged_failure: int = 0 - def __init__(self, router_cache: DualCache, routing_args: dict = {}): + def __init__(self, router_cache: DualCache, routing_args: Optional[dict] = None): self.router_cache = router_cache def log_success_event(self, kwargs, response_obj, start_time, end_time): diff --git a/litellm/router_strategy/lowest_latency.py b/litellm/router_strategy/lowest_latency.py index 20db28fa10e..15628f8001d 100644 --- a/litellm/router_strategy/lowest_latency.py +++ b/litellm/router_strategy/lowest_latency.py @@ -31,8 +31,10 @@ class LowestLatencyLoggingHandler(CustomLogger): logged_success: int = 0 logged_failure: int = 0 - def __init__(self, router_cache: DualCache, routing_args: dict = {}): + def __init__(self, router_cache: DualCache, routing_args: Optional[dict] = None): self.router_cache = router_cache + if routing_args is None: + routing_args = {} self.routing_args = RoutingArgs(**routing_args) def log_success_event( # noqa: PLR0915 diff --git a/litellm/router_strategy/lowest_tpm_rpm.py b/litellm/router_strategy/lowest_tpm_rpm.py index 488f8450941..0c41e43ac2c 100644 --- a/litellm/router_strategy/lowest_tpm_rpm.py +++ b/litellm/router_strategy/lowest_tpm_rpm.py @@ -22,8 +22,10 @@ class LowestTPMLoggingHandler(CustomLogger): logged_failure: int = 0 default_cache_time_seconds: int = 1 * 60 * 60 # 1 hour - def __init__(self, router_cache: DualCache, routing_args: dict = {}): + def __init__(self, router_cache: DualCache, routing_args: Optional[dict] = None): self.router_cache = router_cache + if routing_args is None: + routing_args = {} self.routing_args = RoutingArgs(**routing_args) def log_success_event(self, kwargs, response_obj, start_time, end_time): diff --git a/litellm/router_strategy/lowest_tpm_rpm_v2.py b/litellm/router_strategy/lowest_tpm_rpm_v2.py index 23e8896cd5f..de97033beb8 100644 --- a/litellm/router_strategy/lowest_tpm_rpm_v2.py +++ b/litellm/router_strategy/lowest_tpm_rpm_v2.py @@ -47,8 +47,10 @@ class LowestTPMLoggingHandler_v2(BaseRoutingStrategy, CustomLogger): logged_failure: int = 0 default_cache_time_seconds: int = 1 * 60 * 60 # 1 hour - def __init__(self, router_cache: DualCache, routing_args: dict = {}): + def __init__(self, router_cache: DualCache, routing_args: Optional[dict] = None): self.router_cache = router_cache + if routing_args is None: + routing_args = {} self.routing_args = RoutingArgs(**routing_args) BaseRoutingStrategy.__init__( self, diff --git a/litellm/utils.py b/litellm/utils.py index f902644e760..613e3896b2c 100644 --- a/litellm/utils.py +++ b/litellm/utils.py @@ -2236,7 +2236,9 @@ def encode(model="", text="", custom_tokenizer: Optional[dict] = None): return enc -def decode(model="", tokens: List[int] = [], custom_tokenizer: Optional[dict] = None): +def decode(model="", tokens: Optional[List[int]] = None, custom_tokenizer: Optional[dict] = None): + if tokens is None: + tokens = [] tokenizer_json = custom_tokenizer or _select_tokenizer(model=model) dec = tokenizer_json["tokenizer"].decode(tokens) return dec diff --git a/litellm/vector_stores/vector_store_registry.py b/litellm/vector_stores/vector_store_registry.py index 2596f968a06..070dd47a39c 100644 --- a/litellm/vector_stores/vector_store_registry.py +++ b/litellm/vector_stores/vector_store_registry.py @@ -106,8 +106,8 @@ class VectorStoreIndexRegistry: class VectorStoreRegistry: - def __init__(self, vector_stores: List[LiteLLM_ManagedVectorStore] = []): - self.vector_stores: List[LiteLLM_ManagedVectorStore] = vector_stores + def __init__(self, vector_stores: Optional[List[LiteLLM_ManagedVectorStore]] = None): + self.vector_stores: List[LiteLLM_ManagedVectorStore] = vector_stores or [] self.vector_store_ids_to_vector_store_map: Dict[ str, LiteLLM_ManagedVectorStore ] = {}