{"record":{"id":"768b3e324c033e45","repo":"HKUDS/DeepTutor","slug":"azure-openai-api-base-is-required","errorCode":null,"errorMessage":"Azure OpenAI api_base is required","messagePattern":"Azure OpenAI api_base is required","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"deeptutor/services/llm/provider_core/azure_openai_provider.py","lineNumber":86,"sourceCode":"class AzureOpenAIProvider(LLMProvider):\n    \"\"\"Azure OpenAI provider using the Responses API.\"\"\"\n\n    def __init__(\n        self,\n        api_key: str = \"\",\n        api_base: str = \"\",\n        default_model: str = \"gpt-5.2-chat\",\n        extra_headers: dict[str, str] | None = None,\n        api_version: str | None = None,\n    ):\n        super().__init__(api_key, api_base)\n        self.default_model = default_model\n        self.extra_headers = extra_headers or {}\n\n        if not api_key:\n            raise ValueError(\"Azure OpenAI api_key is required\")\n        if not api_base:\n            raise ValueError(\"Azure OpenAI api_base is required\")\n\n        base_url = normalize_azure_base_url(api_base)\n\n        # Azure authenticates API keys through ``api-key``; the SDK only sends\n        # ``Authorization: Bearer``, which the service reserves for Entra tokens.\n        headers = {\"x-session-affinity\": uuid.uuid4().hex, \"api-key\": api_key}\n        if extra_headers:\n            headers.update(extra_headers)\n\n        # The ``/openai/v1`` surface supersedes ``?api-version=``, so a classic\n        # dated version configured for the probe's URL would be rejected here.\n        # Only ``preview`` is forwarded, since Azure still gates preview-only\n        # Responses features behind it.\n        default_query = (\n            {\"api-version\": \"preview\"} if (api_version or \"\").strip().lower() == \"preview\" else None\n        )\n\n        self._client = AsyncOpenAI(","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/HKUDS/DeepTutor/blob/3e82f130422a813cdd73c10b21a44e9325f5821a/deeptutor/services/llm/provider_core/azure_openai_provider.py#L68-L104","documentation":"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.","triggerScenarios":"Constructing the Azure provider with api_base=None/'' — the resource endpoint was never configured, or the field name differs (endpoint vs api_base).","commonSituations":"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.","solutions":["Set api_base to your Azure resource endpoint (https://<resource>.openai.azure.com/, optionally with /openai/deployments/<deployment>/api path).","Verify the resource name and region in the Azure portal.","Ensure normalize_azure_base_url receives a well-formed URL."],"exampleFix":"# before\nprov = AzureOpenAIProvider(api_key=k, api_base=None)\n# after\nprov = AzureOpenAIProvider(api_key=k, api_base='https://myres.openai.azure.com/')","handlingStrategy":"validation","validationCode":"from urllib.parse import urlparse\n\ndef azure_base_valid(base: str | None) -> bool:\n    if not base:\n        return False\n    u = urlparse(base)\n    return u.scheme == 'https' and '.openai.azure.com' in u.netloc","typeGuard":null,"tryCatchPattern":"try:\n    prov = AzureOpenAIProvider(api_key=key, api_base=base)\nexcept ValueError as e:\n    if 'api_base' in str(e):\n        raise SystemExit('Set AZURE_OPENAI_ENDPOINT to your resource URL') from e\n    raise","preventionTips":["Include endpoint in the same startup validation as the key","Document the expected URL shape next to the setting","Use the Azure portal to copy exact resource endpoints"],"tags":["config","azure","missing-endpoint"],"backgroundTag":"missing-required-config","analyzedSha":"3e82f130422a813cdd73c10b21a44e9325f5821a","analyzedAt":"2026-08-27T06:57:25.364Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}