From 86955f071c73d4cf0ae26ea5561be612fee1f14d Mon Sep 17 00:00:00 2001 From: yucheng Date: Thu, 8 Oct 2026 04:30:12 +0000 Subject: [PATCH] fix(azure_storage): map the encrypted response id algorithm tag to an ADLS safe file name Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- litellm/integrations/azure_storage/azure_storage.py | 8 ++++---- .../unit/integrations/azure_storage/test_azure_storage.py | 2 ++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/litellm/integrations/azure_storage/azure_storage.py b/litellm/integrations/azure_storage/azure_storage.py index 018ff758d5d..a59b86934f0 100644 --- a/litellm/integrations/azure_storage/azure_storage.py +++ b/litellm/integrations/azure_storage/azure_storage.py @@ -31,14 +31,14 @@ from litellm.types.secret_managers.get_azure_ad_token_provider import ( from litellm.types.utils import StandardLoggingPayload AZURE_STORAGE_TOKEN_SCOPE: Final = "https://storage.azure.com/.default" -_ADLS_SAFE_NAME: Final = str.maketrans("/", "_", "=") +_ADLS_SAFE_NAME: Final = str.maketrans("/:", "__", "=") _DOT_OR_EMPTY_SEGMENTS: Final = frozenset(("", ".", "..")) def adls_safe_file_name(payload_id: str | None) -> str: - """A Responses API id is base64 behind `resp_`, and the Data Lake service rejects its `=` padding and `/`, so - that name drops the padding and maps `/` to `_`. Standard base64 has no `_` and its padding is fixed by the - length, so those ids stay distinct. Every other id, including a caller's `x-litellm-call-id`, is used as is + """A Responses API id is base64 behind `resp_`, with a `v3:gcm:` style algorithm tag when the proxy encrypts it, + and the Data Lake service rejects its `=` padding, `/` and `:`, so that name drops the padding and maps `/` and + `:` to `_`. Standard base64 has no `_` and its padding is fixed by the length, so those ids stay distinct. Every other id, including a caller's `x-litellm-call-id`, is used as is unless it has an empty, `.` or `..` path segment, which gets the same rewrite so the file keeps its own name in the log directory""" name: Final = payload_id or str(uuid.uuid4()) diff --git a/tests/unit/integrations/azure_storage/test_azure_storage.py b/tests/unit/integrations/azure_storage/test_azure_storage.py index 01b17edd2cf..ec0dd1c6a8f 100644 --- a/tests/unit/integrations/azure_storage/test_azure_storage.py +++ b/tests/unit/integrations/azure_storage/test_azure_storage.py @@ -436,6 +436,8 @@ async def test_service_client_is_replaced_at_the_exact_ttl_boundary(mock_env_var ("resp_YWJjZGU=", "resp_YWJjZGU.json"), ("resp_+/8=", "resp_+_8.json"), ("resp_a+b", "resp_a+b.json"), + ("resp_v3:gcm:a-b_c==", "resp_v3_gcm_a-b_c.json"), + ("resp_v2:gcm:a-b_c=", "resp_v2_gcm_a-b_c.json"), ("chatcmpl-abc123", "chatcmpl-abc123.json"), ), )