diff --git a/litellm/proxy/proxy_server.py b/litellm/proxy/proxy_server.py index 927d0ae8e8..2672ec252d 100644 --- a/litellm/proxy/proxy_server.py +++ b/litellm/proxy/proxy_server.py @@ -2105,13 +2105,19 @@ async def _init_and_increment_window_spend_counter( window_start: Optional[datetime], increment: float, ): - if window_start is not None: - await _ensure_window_spend_counter_initialized( - counter_key=counter_key, - entity_type=entity_type, - entity_id=entity_id, - window_start=window_start, + if window_start is None: + verbose_proxy_logger.warning( + "Skipping spend counter increment for invalid budget window %s", + counter_key, ) + return + + await _ensure_window_spend_counter_initialized( + counter_key=counter_key, + entity_type=entity_type, + entity_id=entity_id, + window_start=window_start, + ) await _increment_spend_counter_cache(counter_key=counter_key, increment=increment) diff --git a/tests/test_litellm/proxy/test_proxy_server.py b/tests/test_litellm/proxy/test_proxy_server.py index dd6ef04bc9..5edff6d903 100644 --- a/tests/test_litellm/proxy/test_proxy_server.py +++ b/tests/test_litellm/proxy/test_proxy_server.py @@ -5324,6 +5324,36 @@ async def test_window_spend_counter_redis_clean_miss_skips_stale_in_memory(): ps.prisma_client = orig_prisma +@pytest.mark.asyncio +async def test_window_spend_counter_skips_invalid_window_start(): + from litellm.caching.dual_cache import DualCache + from litellm.proxy.proxy_server import _init_and_increment_window_spend_counter + + counter_cache = DualCache() + + import litellm.proxy.proxy_server as ps + + orig_counter = ps.spend_counter_cache + ps.spend_counter_cache = counter_cache + try: + await _init_and_increment_window_spend_counter( + counter_key="spend:key:key-invalid-window:window:not-a-duration", + entity_type="Key", + entity_id="key-invalid-window", + window_start=None, + increment=0.5, + ) + + assert ( + counter_cache.in_memory_cache.get_cache( + key="spend:key:key-invalid-window:window:not-a-duration" + ) + is None + ) + finally: + ps.spend_counter_cache = orig_counter + + @pytest.mark.asyncio async def test_increment_spend_counters_finalizes_after_unreserved_increments(): from litellm.caching.dual_cache import DualCache