BerriAI/litellm · error · AuthenticationError
Azure AD authentication failed for Redis
Error message
Azure AD authentication failed for Redis
What it means
For Azure Cache for Redis with Entra ID auth, litellm sends AUTH with an access token (with a fallback to single-arg AUTH for older Redis). If the server's reply is not 'OK', redis.AuthenticationError('Azure AD authentication failed for Redis') is raised: the token was rejected — wrong audience, unauthorized identity, or token acquisition issues.
Solutions
- In the Azure cache's Data Access (IAM) settings, add the connecting identity as Redis User/Contributor
- Verify the credential: unset AZURE_CLIENT_SECRET to test DefaultAzureCredential/Managed Identity, or refresh the rotated secret
- Ensure Entra authentication is actually enabled on the cache and you connect over TLS (port 6380) to the correct host
- Remove any legacy password from the Redis URL/config so the AAD path is used consistently
Example fix
# before REDIS_HOST=mycache.redis.cache.windows.net REDIS_PORT=6380 export REDIS_AZURE_AD_TOKEN=true # identity not in cache ACL -> AuthenticationError: Azure AD authentication failed for Redis # after az redis access-policy-assignment create ... # or Portal: Data access -> Add identity (Redis User) # redeploy proxy; AUTH now returns OK
Defensive patterns
Strategy: try-catch
Validate before calling
from azure.identity import DefaultAzureCredential
def can_get_azure_token(scope: str) -> bool:
"""Pre-flight: can we even acquire an Entra token for the cache?"""
try:
DefaultAzureCredential().get_token(scope)
return True
except Exception:
return False
# scope is typically "https://<cache-name>.redis.cache.windows.net/.default" Try / catch
from redis.exceptions import AuthenticationError
try:
cache = RedisCache(host="mycache.redis.cache.windows.net", port=6380,
azure_redis_ad_token=True, ssl=True)
cache.ping()
except AuthenticationError as e:
if "Azure AD" in str(e):
raise RuntimeError(
"Entra token rejected: add this identity as Redis User in the cache's "
"Data Access settings and verify AZURE_* credential env vars"
) from e
raise Prevention
- Add the connecting identity (managed identity or SP) under the cache's Data access configuration before enabling AAD
- In IaC, declare the Redis access policy assignment alongside the cache so it can't drift
- Monitor secret expiry if using ClientSecretCredential; prefer managed identity on Azure compute
- Keep key-based auth out of the URL when using the AAD path to avoid mixed auth
When it happens
Trigger: azure_redis_ad_token=true while AZURE_CLIENT_ID/TENANT_ID/CLIENT_SECRET (or ManagedIdentityCredential) produce a token that the cache rejects: identity lacks Redis ACL/Contributor permissions, token audience mismatch for the cache endpoint, or connecting with access keys auth configured on the cache while sending Entra tokens.
Common situations: Azure Cache with 'Entra ID authentication' enabled but the managed identity not added under Data access configuration; ClientSecretCredential with an expired/rotated secret in a long-running proxy; local dev with az login identity that has no Redis role; mixing key-based URL (password in REDIS_URL) with AAD path.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- azure-identity is required for Azure AD Redis…
- GCP IAM authentication failed
- 500
- 503
- Both 'sentinel_nodes' and 'service_name' are required for…
AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18).
Data as JSON: /api/errors/e0f351d41754c3c8.
Report an issue: GitHub.
Appendix: source
Thrown at litellm/_redis.py:322
# Only include username when explicitly set — sending AUTH "" <token>
# is invalid for most ACL-configured Azure Redis instances.
username: Final = os.environ.get("REDIS_USERNAME", "")
if username:
auth_args = (username, access_token)
else:
auth_args = (access_token,)
self.send_command("AUTH", *auth_args, check_health=False)
try:
auth_response = self.read_response()
except AuthenticationWrongNumberOfArgsError:
# Fallback: try with just the token (Redis < 6 / no ACL)
self.send_command("AUTH", access_token, check_health=False)
auth_response = self.read_response()
if str_if_bytes(auth_response) != "OK":
raise AuthenticationError("Azure AD authentication failed for Redis")
# Attach the live credential object so async paths can wrap it in
# AzureADCredentialProvider for refresh-aware token retrieval. The raw
# client_id/tenant_id/secret are intentionally NOT exposed here — the
# credential closure already holds them.
ad_connect._azure_credential = credential
return ad_connect
def get_redis_url_from_environment():
if "REDIS_URL" in os.environ:
return os.environ["REDIS_URL"]
if "REDIS_HOST" not in os.environ or "REDIS_PORT" not in os.environ:
raise ValueError("Either 'REDIS_URL' or both 'REDIS_HOST' and 'REDIS_PORT' must be specified for Redis.")
if "REDIS_SSL" in os.environ and os.environ["REDIS_SSL"].lower() == "true":
redis_protocol = "rediss"View on GitHub (pinned to 77b7c6c40c)