diff --git a/litellm/proxy/proxy_server.py b/litellm/proxy/proxy_server.py index cac8a9d6893..7a374e16aa1 100644 --- a/litellm/proxy/proxy_server.py +++ b/litellm/proxy/proxy_server.py @@ -910,7 +910,7 @@ async def proxy_shutdown_event(worker_heartbeat: ProxyWorkerHeartbeat | None = N if litellm.cache is not None: try: await litellm.cache.disconnect() - except Exception as e: + except Exception as e: # noqa: BLE001 # cache teardown must not abort remaining shutdown steps verbose_proxy_logger.debug("Error disconnecting litellm.cache: %s", e) await jwt_handler.close() diff --git a/tests/test_litellm/proxy/proxy_server/test_lifecycle.py b/tests/test_litellm/proxy/proxy_server/test_lifecycle.py index a06e7142122..8f8ef819a95 100644 --- a/tests/test_litellm/proxy/proxy_server/test_lifecycle.py +++ b/tests/test_litellm/proxy/proxy_server/test_lifecycle.py @@ -205,6 +205,31 @@ async def test_proxy_shutdown_event_prisma_disconnect_raises_error(monkeypatch): await proxy_shutdown_event() +@pytest.mark.asyncio +async def test_proxy_shutdown_event_cache_disconnect_error_does_not_abort_shutdown(monkeypatch): + """A cache backend failing to disconnect must not skip the jwt_handler close + that runs after it, unlike a prisma disconnect failure which does abort. + """ + monkeypatch.setattr(ps, "prisma_client", None, raising=False) + + fake_jwt = MagicMock() + fake_jwt.close = AsyncMock() + monkeypatch.setattr(ps, "jwt_handler", fake_jwt, raising=False) + monkeypatch.setattr(ps, "db_writer_client", None, raising=False) + + import litellm + + fake_cache = MagicMock() + fake_cache.disconnect = AsyncMock(side_effect=RuntimeError("redis gone")) + monkeypatch.setattr(litellm, "cache", fake_cache, raising=False) + monkeypatch.setattr(litellm, "success_callback", [], raising=False) + + await proxy_shutdown_event() + + assert fake_cache.disconnect.await_count == 1 + assert fake_jwt.close.await_count == 1 + + # --------------------------------------------------------------------------- # _flush_spend_logs_queue_on_shutdown # ---------------------------------------------------------------------------