Skip to content

[Bug]: Azure storage callback logs #9339

@ma-armenta

Description

@ma-armenta

What happened?

Sending logs over to an Azure storage container doesn't seem to be working as expected / documented. I suspected connection or auth issues, but rule them out with a sample script below, to connect to the container and create / write a new file. It seems to be the client is not closed properly? Haven't dive in the code just yet.

import os
from azure.storage.blob import BlobServiceClient, ContainerClient
from azure.identity import DefaultAzureCredential

def validate_blob_storage_connectivity():
    try:
        # Retrieve the storage account name and key from environment variables
        account_name = os.getenv('AZURE_STORAGE_ACCOUNT_NAME')
        account_key = os.getenv('AZURE_STORAGE_ACCOUNT_KEY')
        if not account_name or not account_key:
            raise ValueError("AZURE_STORAGE_ACCOUNT_NAME or AZURE_STORAGE_ACCOUNT_KEY environment variable not set")

        # Create the BlobServiceClient object using the account name and key
        blob_service_client = BlobServiceClient(
            account_url=f"https://{account_name}.blob.core.windows.net",
            credential=account_key
        )

        # Retrieve the container name from environment variables
        container_name = os.getenv('AZURE_STORAGE_FILE_SYSTEM')
        if not container_name:
            raise ValueError("AZURE_STORAGE_FILE_SYSTEM environment variable not set")

        # Create the ContainerClient object
        container_client = blob_service_client.get_container_client(container_name)

        # Check if the container exists
        if container_client.exists():
            print(f"Successfully connected to the container: {container_name}")
            # Create a new blob called 'test-litellm'
            blob_client = container_client.get_blob_client("test-litellm")
            blob_client.upload_blob("This is a test blob.", overwrite=True)
            print("Created a new blob called 'test-litellm'")
            for b in container_client.list_blobs():
                print(b)
        else:
            print(f"Container {container_name} does not exist")

    except Exception as e:
        print(f"Failed to connect to Azure Blob Storage: {e}")

if __name__ == "__main__":
    validate_blob_storage_connectivity()

Relevant log output

14:08:11 - LiteLLM:ERROR: azure_storage.py:381 - Error occurred: You are attempting to read or stream the content from request <HttpRequest [HEAD], url: 'https://<account>.blob.core.windows.net/<container-name>/2025-03-18'>. You have likely already consumed this stream, so it can not be accessed anymore.
Traceback (most recent call last):
  File "/usr/lib/python3.13/site-packages/litellm/integrations/azure_storage/azure_storage.py", line 356, in upload_to_azure_data_lake_with_azure_account_key
    if not await directory_client.exists():
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.13/site-packages/azure/core/tracing/decorator_async.py", line 114, in wrapper_use_tracer
    return await func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.13/site-packages/azure/storage/filedatalake/aio/_data_lake_directory_client_async.py", line 195, in exists
    return await self._exists(**kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.13/site-packages/azure/storage/filedatalake/aio/_path_client_async.py", line 760, in _exists
    return await self._blob_client.exists(**kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.13/site-packages/azure/core/tracing/decorator_async.py", line 114, in wrapper_use_tracer
    return await func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.13/site-packages/azure/storage/blob/aio/_blob_client_async.py", line 884, in exists
    await self._client.blob.get_properties(
    ...<2 lines>...
        **kwargs)
  File "/usr/lib/python3.13/site-packages/azure/core/tracing/decorator_async.py", line 114, in wrapper_use_tracer
    return await func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.13/site-packages/azure/storage/blob/_generated/aio/operations/_blob_operations.py", line 508, in get_properties
    pipeline_response: PipelineResponse = await self._client._pipeline.run(  # pylint: disable=protected-access
                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        _request, stream=_stream, **kwargs
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    )
    ^
  File "/usr/lib/python3.13/site-packages/azure/core/pipeline/_base_async.py", line 229, in run
    return await first_node.send(pipeline_request)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.13/site-packages/azure/core/pipeline/_base_async.py", line 77, in send
    response = await self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.13/site-packages/azure/core/pipeline/_base_async.py", line 77, in send
    response = await self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.13/site-packages/azure/core/pipeline/_base_async.py", line 77, in send
    response = await self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  [Previous line repeated 5 more times]
  File "/usr/lib/python3.13/site-packages/azure/core/pipeline/policies/_redirect_async.py", line 76, in send
    response = await self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.13/site-packages/azure/core/pipeline/_base_async.py", line 77, in send
    response = await self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.13/site-packages/azure/storage/filedatalake/_shared/policies_async.py", line 140, in send
    raise err
  File "/usr/lib/python3.13/site-packages/azure/storage/filedatalake/_shared/policies_async.py", line 114, in send
    response = await self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.13/site-packages/azure/core/pipeline/_base_async.py", line 77, in send
    response = await self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.13/site-packages/azure/storage/filedatalake/_shared/policies_async.py", line 67, in send
    await response.http_response.load_body()
  File "/usr/lib/python3.13/site-packages/azure/core/rest/_aiohttp.py", line 165, in _load_body
    self._content = await self.read()  # type: ignore
                    ^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.13/site-packages/azure/core/rest/_aiohttp.py", line 214, in read
    self._stream_download_check()
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~^^
  File "/usr/lib/python3.13/site-packages/azure/core/rest/_http_response_impl.py", line 336, in _stream_download_check
    raise StreamConsumedError(self)
azure.core.exceptions.StreamConsumedError: You are attempting to read or stream the content from request <HttpRequest [HEAD], url: 'https://<account>.blob.core.windows.net/<container-name>/2025-03-18'>. You have likely already consumed this stream, so it can not be accessed anymore.
Unclosed client session
client_session: <aiohttp.client.ClientSession object at 0x7f1975a56ad0>
Unclosed connector
connections: ['[(<aiohttp.client_proto.ResponseHandler object at 0x7f1938348410>, 72098.666)]']
connector: <aiohttp.connector.TCPConnector object at 0x7f19507cb360>

Are you a ML Ops Team?

Yes

What LiteLLM version are you on ?

v1.63.11-stable

Twitter / LinkedIn details

https://www.linkedin.com/in/maarmenta/

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions