fix(azure): default max_retries to DEFAULT_MAX_RETRIES with regression tests

initialize_azure_sdk_client now always sets max_retries, falling back to
litellm.constants.DEFAULT_MAX_RETRIES when the caller passes none, so the
DEFAULT_MAX_RETRIES env var reaches every Azure SDK client the same way it
already does for the OpenAI and Azure completion and embedding paths.
This commit is contained in:
mateo-berri 2026-09-09 13:16:33 -07:00
parent 6b673749ac
commit a0f2fbbec2
2 changed files with 54 additions and 7 deletions

View file

@ -11,6 +11,7 @@ from openai import AsyncAzureOpenAI, AsyncOpenAI, AzureOpenAI, OpenAI
import litellm
from litellm._logging import verbose_logger
from litellm.caching.caching import DualCache
from litellm.constants import DEFAULT_MAX_RETRIES
from litellm.llms.base_llm.chat.transformation import BaseLLMException
from litellm.llms.openai.common_utils import BaseOpenAILLM
from litellm.secret_managers.get_azure_ad_token_provider import (
@ -536,11 +537,8 @@ class BaseAzureLLM(BaseOpenAILLM):
if scope is None:
scope = "https://cognitiveservices.azure.com/.default"
max_retries = litellm_params.get("max_retries")
if max_retries is None:
from litellm.constants import DEFAULT_MAX_RETRIES
max_retries = DEFAULT_MAX_RETRIES
configured_max_retries: Final = litellm_params.get("max_retries")
max_retries: Final = DEFAULT_MAX_RETRIES if configured_max_retries is None else configured_max_retries
timeout: Final = litellm_params.get("timeout")
if not api_key and azure_ad_token_provider is None and tenant_id and client_id and client_secret:
verbose_logger.debug("Using Azure AD Token Provider from Entra ID for Azure Auth")
@ -600,8 +598,7 @@ class BaseAzureLLM(BaseOpenAILLM):
else:
azure_client_params["http_client"] = self._get_sync_http_client()
if max_retries is not None:
azure_client_params["max_retries"] = max_retries
azure_client_params["max_retries"] = max_retries
if timeout is not None:
azure_client_params["timeout"] = timeout

View file

@ -1,5 +1,6 @@
import json
import os
import subprocess
import sys
import traceback
from typing import Callable, Optional
@ -414,6 +415,55 @@ def test_select_azure_base_url_called(setup_mocks):
setup_mocks["select_url"].assert_called_once()
def test_initialize_defaults_max_retries_to_litellm_default(setup_mocks):
result = BaseAzureLLM().initialize_azure_sdk_client(
litellm_params={},
api_key="test-api-key",
api_base="https://test.openai.azure.com",
model_name="gpt-4",
api_version="2023-06-01",
is_async=False,
)
assert result["max_retries"] == litellm.constants.DEFAULT_MAX_RETRIES
@pytest.mark.parametrize(
"configured, expected",
[(0, 0), (5, 5), (None, litellm.constants.DEFAULT_MAX_RETRIES)],
)
def test_initialize_honors_explicit_max_retries(setup_mocks, configured, expected):
result = BaseAzureLLM().initialize_azure_sdk_client(
litellm_params={"max_retries": configured},
api_key="test-api-key",
api_base="https://test.openai.azure.com",
model_name="gpt-4",
api_version="2023-06-01",
is_async=False,
)
assert result["max_retries"] == expected
def test_default_max_retries_env_var_reaches_azure_sdk_client():
code = (
"from litellm.llms.azure.common_utils import BaseAzureLLM\n"
"client = BaseAzureLLM().get_azure_openai_client("
"api_key='test-api-key', api_base='https://test.openai.azure.com', api_version='2024-02-01',"
" client=None, _is_async=True, litellm_params={}, model='gpt-4')\n"
"print(client.max_retries)"
)
completed = subprocess.run(
[sys.executable, "-c", code],
env={**os.environ, "DEFAULT_MAX_RETRIES": "0"},
capture_output=True,
text=True,
check=True,
)
assert completed.stdout.strip() == "0"
@pytest.mark.parametrize(
"call_type",
[