From 5a5ea34ef8302147e6920a25382041b21e160981 Mon Sep 17 00:00:00 2001 From: revanth-045 Date: Tue, 29 Sep 2026 15:50:04 +0530 Subject: [PATCH] fix(caching): overwrite existing blobs in AzureBlobCache.set_cache MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The sync path called `upload_blob(key, serialized_value)`. `ContainerClient.upload_blob` defaults to `overwrite=False` and raises `ResourceExistsError` when the blob already exists, and `set_cache` swallows exceptions by design — so re-caching a key was a silent no-op and the entry stayed at its first value forever. `async_set_cache` in the same class already passes `overwrite=True`. The existing sync test asserted the call without `overwrite`, pinning the bug; updated alongside. Co-Authored-By: Claude Opus 5 --- litellm/caching/azure_blob_cache.py | 2 +- tests/unit/caching/test_azure_blob_cache.py | 28 ++++++++++++++++++++- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/litellm/caching/azure_blob_cache.py b/litellm/caching/azure_blob_cache.py index 742932731b3..bfd3da2fcc3 100644 --- a/litellm/caching/azure_blob_cache.py +++ b/litellm/caching/azure_blob_cache.py @@ -44,7 +44,7 @@ class AzureBlobCache(BaseCache): print_verbose(f"LiteLLM SET Cache - Azure Blob. Key={key}. Value={value}") serialized_value: Final = json.dumps(value) try: - self.container_client.upload_blob(key, serialized_value) + self.container_client.upload_blob(key, serialized_value, overwrite=True) except Exception as e: # NON blocking - notify users Azure Blob is throwing an exception print_verbose(f"LiteLLM set_cache() - Got exception from Azure Blob: {e}") diff --git a/tests/unit/caching/test_azure_blob_cache.py b/tests/unit/caching/test_azure_blob_cache.py index 63f4681fd06..26c09fdd415 100644 --- a/tests/unit/caching/test_azure_blob_cache.py +++ b/tests/unit/caching/test_azure_blob_cache.py @@ -157,10 +157,36 @@ def test_blob_cache_sync_set_cache(mock_azure_dependencies): # Verify the call was made correctly cache.container_client.upload_blob.assert_called_once_with( - "sync_test_key", '{"sync_key": "sync_value", "number": 123}' + "sync_test_key", '{"sync_key": "sync_value", "number": 123}', overwrite=True ) +def test_blob_cache_sync_set_cache_replaces_an_existing_key(mock_azure_dependencies): + """Re-caching a key must replace the blob, as the async path already does. + + `ContainerClient.upload_blob` defaults to `overwrite=False` and raises + `ResourceExistsError` for a key that is already present. `set_cache` + swallows that, so without `overwrite=True` the entry silently never updates. + """ + from azure.core.exceptions import ResourceExistsError + + cache = AzureBlobCache("https://my-test-host", "test-container") + + existing_keys = {"sync_test_key"} + + def upload_blob(name, data, **kwargs): + if name in existing_keys and not kwargs.get("overwrite"): + raise ResourceExistsError("The specified blob already exists.") + existing_keys.add(name) + return MagicMock() + + cache.container_client.upload_blob.side_effect = upload_blob + + cache.set_cache("sync_test_key", {"v": 2}) + + assert cache.container_client.upload_blob.call_args.kwargs.get("overwrite") is True + + def test_blob_cache_sync_get_cache_not_found(mock_azure_dependencies): """Test sync get_cache method when blob is not found"""