HKUDS/DeepTutor · error · ValueError

Azure OpenAI api_base is required

Error message

Azure OpenAI api_base is required

What it means

AzureOpenAIProvider.__init__ also requires api_base because Azure endpoints are per-resource URLs (https://<resource>.openai.azure.com/) that cannot be defaulted like OpenAI's api.openai.com.

Source

Thrown at deeptutor/services/llm/provider_core/azure_openai_provider.py:86

class AzureOpenAIProvider(LLMProvider):
    """Azure OpenAI provider using the Responses API."""

    def __init__(
        self,
        api_key: str = "",
        api_base: str = "",
        default_model: str = "gpt-5.2-chat",
        extra_headers: dict[str, str] | None = None,
        api_version: str | None = None,
    ):
        super().__init__(api_key, api_base)
        self.default_model = default_model
        self.extra_headers = extra_headers or {}

        if not api_key:
            raise ValueError("Azure OpenAI api_key is required")
        if not api_base:
            raise ValueError("Azure OpenAI api_base is required")

        base_url = normalize_azure_base_url(api_base)

        # Azure authenticates API keys through ``api-key``; the SDK only sends
        # ``Authorization: Bearer``, which the service reserves for Entra tokens.
        headers = {"x-session-affinity": uuid.uuid4().hex, "api-key": api_key}
        if extra_headers:
            headers.update(extra_headers)

        # The ``/openai/v1`` surface supersedes ``?api-version=``, so a classic
        # dated version configured for the probe's URL would be rejected here.
        # Only ``preview`` is forwarded, since Azure still gates preview-only
        # Responses features behind it.
        default_query = (
            {"api-version": "preview"} if (api_version or "").strip().lower() == "preview" else None
        )

        self._client = AsyncOpenAI(

View on GitHub (pinned to 3e82f13042)

Solutions

  1. Set api_base to your Azure resource endpoint (https://<resource>.openai.azure.com/, optionally with /openai/deployments/<deployment>/api path).
  2. Verify the resource name and region in the Azure portal.
  3. Ensure normalize_azure_base_url receives a well-formed URL.

Example fix

# before
prov = AzureOpenAIProvider(api_key=k, api_base=None)
# after
prov = AzureOpenAIProvider(api_key=k, api_base='https://myres.openai.azure.com/')
Defensive patterns

Strategy: validation

Validate before calling

from urllib.parse import urlparse

def azure_base_valid(base: str | None) -> bool:
    if not base:
        return False
    u = urlparse(base)
    return u.scheme == 'https' and '.openai.azure.com' in u.netloc

Try / catch

try:
    prov = AzureOpenAIProvider(api_key=key, api_base=base)
except ValueError as e:
    if 'api_base' in str(e):
        raise SystemExit('Set AZURE_OPENAI_ENDPOINT to your resource URL') from e
    raise

Prevention

When it happens

Trigger: Constructing the Azure provider with api_base=None/'' — the resource endpoint was never configured, or the field name differs (endpoint vs api_base).

Common situations: Confusing the Azure 'endpoint' setting with the deployment name; copy-paste config that only set the key; using an OpenAI-style base_url that got lost in normalization.

Understand the failure class

Background: "X is required", "must be set", "cannot be empty": the missing-required-config error family, from Vertex AI project/location to WeChat keys — this error's family across 18 libraries.

Related errors


AI-assisted analysis of HKUDS/DeepTutor@3e82f13042 (2026-08-27). Data as JSON: /api/errors/768b3e324c033e45. Report an issue: GitHub.