BerriAI/litellm · error · AzureOpenAIError

max retries must be an int

Error message

max retries must be an int

What it means

Before constructing the sync AzureOpenAI SDK client for text completion, LiteLLM pops max_retries from optional_params (default 2) and requires it to be an int; anything else raises AzureOpenAIError 422. The OpenAI SDK's max_retries parameter is passed straight through, so a non-int would fail deeper with a worse message.

Source

Thrown at litellm/llms/azure/completion/handler.py:141

                    client=client,
                )
            else:
                ## LOGGING
                logging_obj.pre_call(
                    input=prompt,
                    api_key=api_key,
                    additional_args={
                        "headers": {
                            "api_key": api_key,
                            "azure_ad_token": azure_ad_token,
                        },
                        "api_version": api_version,
                        "api_base": api_base,
                        "complete_input_dict": data,
                    },
                )
                if not isinstance(max_retries, int):
                    raise AzureOpenAIError(status_code=422, message="max retries must be an int")
                # init AzureOpenAI Client
                azure_client: Final = self.get_azure_openai_client(
                    api_key=api_key,
                    api_base=api_base,
                    api_version=api_version,
                    client=client,
                    litellm_params=litellm_params,
                    _is_async=False,
                    model=model,
                )

                if not isinstance(azure_client, AzureOpenAI):
                    raise AzureOpenAIError(
                        status_code=500,
                        message="azure_client is not an instance of AzureOpenAI",
                    )

                raw_response: Final = azure_client.completions.with_raw_response.create(**data, timeout=timeout)

View on GitHub (pinned to 6c2dcb801b)

Solutions

  1. Pass an int: litellm.text_completion(..., max_retries=3).
  2. Coerce config-sourced values: max_retries=int(cfg["max_retries"]) with a safe default.
  3. In proxy configs, put the literal integer in YAML rather than an env-string substitution.

Example fix

# before
max_retries = os.environ.get("MAX_RETRIES", "2")  # str!

# after
max_retries = int(os.environ.get("MAX_RETRIES", "2"))
Defensive patterns

Strategy: type-guard

Validate before calling

max_retries = cfg.get("max_retries", 2)
assert isinstance(max_retries, int) and not isinstance(max_retries, bool), "max_retries must be int"

Type guard

def is_int_retries(v: object) -> bool:
    return isinstance(v, int) and not isinstance(v, bool)

Try / catch

try:
    resp = litellm.text_completion(..., max_retries=cfg["max_retries"])
except AzureOpenAIError as e:
    if e.status_code == 422 and "max retries" in str(e):
        resp = litellm.text_completion(..., max_retries=int(cfg["max_retries"]))
    else:
        raise

Prevention

When it happens

Trigger: Passing max_retries="5" (string from an env var or config file), max_retries=5.0, or None through optional_params to the azure text-completion path.

Common situations: Proxy YAML configs where numeric-looking values come from os.environ/<VAR> substitutions that yield strings; JSON configs with float values; templating systems that stringify numbers.

Related errors


AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15). Data as JSON: /api/errors/248542cb542c87a9. Report an issue: GitHub.