BerriAI/litellm · error · AzureOpenAIError

azure_client is not an instance of AzureOpenAI or OpenAI

Error message

azure_client is not an instance of AzureOpenAI or OpenAI

What it means

An internal invariant check in the sync Azure OpenAI chat completion path: after `get_azure_openai_client` builds or accepts a passed-in client, it must be an instance of AzureOpenAI or OpenAI. A 500 is raised otherwise. Almost always means a caller injected a custom `client` object of the wrong type.

Source

Thrown at litellm/llms/azure/azure.py:341

                        "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_version=api_version,
                    api_base=api_base,
                    api_key=api_key,
                    model=model,
                    client=client,
                    _is_async=False,
                    litellm_params=litellm_params,
                )
                if not isinstance(azure_client, (AzureOpenAI, OpenAI)):
                    raise AzureOpenAIError(
                        status_code=500,
                        message="azure_client is not an instance of AzureOpenAI or OpenAI",
                    )

                headers, response = self.make_sync_azure_openai_chat_completion_request(
                    azure_client=azure_client, data=data, timeout=timeout
                )
                if isinstance(response, str):
                    raise AzureOpenAIError(
                        status_code=500,
                        message=f"Unexpected string response from Azure: {response[:500]}",
                    )
                stringified_response: Final = response.model_dump()
                ## LOGGING
                logging_obj.post_call(
                    input=messages,
                    api_key=api_key,
                    original_response=stringified_response,

View on GitHub (pinned to 6c2dcb801b)

Solutions

  1. If you pass a custom client, construct it with openai.AzureOpenAI(...) for sync calls.
  2. Otherwise omit the client argument and let LiteLLM build it from api_base/api_key.
  3. For async calls use litellm.acompletion so the async client path is used.

Example fix

# before
client = openai.AsyncAzureOpenAI(api_key=k, azure_endpoint=base)
litellm.completion(model='azure/gpt-4o', messages=msgs, client=client)

# after
client = openai.AzureOpenAI(api_key=k, azure_endpoint=base, api_version='2024-06-01')
litellm.completion(model='azure/gpt-4o', messages=msgs, client=client)
Defensive patterns

Strategy: type-guard

Validate before calling

if client is not None and not isinstance(client, (openai.AzureOpenAI, openai.OpenAI)):
    raise TypeError('client must be an openai.AzureOpenAI/OpenAI instance for sync calls')

Type guard

from openai import AzureOpenAI, OpenAI

def is_sync_azure_client(c) -> bool:
    return isinstance(c, (AzureOpenAI, OpenAI))

Prevention

When it happens

Trigger: Passing client=<httpx.AsyncClient or custom wrapper> to a sync completion call; passing an AsyncAzureOpenAI client to the sync path; mocking the client in tests with an object that is not an SDK instance.

Common situations: Users constructing their own OpenAI SDK client for connection tuning and passing the async variant; test doubles replacing the client.

Related errors


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