openai/openai-python · critical · SubjectTokenProviderError

Failed to fetch Azure subject token from IMDS: {e}

Error message

Failed to fetch Azure subject token from IMDS: {e}

What it means

The catch-all wrapper for the Azure managed-identity flow: any exception during the IMDS request not already handled (connection refused/timeout to 169.254.169.254, DNS issues, TLS problems, JSON decode errors on the response) is re-raised as SubjectTokenProviderError with the original cause attached. The '{e}' text identifies the transport-level problem — most commonly the metadata endpoint is unreachable, meaning you're not on an Azure host or egress is blocked.

Source

Thrown at src/openai/auth/_workload.py:158

                response = http_client.get(url, params=params, headers={"Metadata": "true"}, timeout=timeout)
            else:
                with httpx2.Client() as client:
                    response = client.get(url, params=params, headers={"Metadata": "true"}, timeout=timeout)

            if response.is_error:
                raise SubjectTokenProviderError(
                    f"Failed to fetch Azure subject token from IMDS: HTTP {response.status_code}",
                    response=response,
                )
            data = response.json()
            token = data.get("access_token")
            if not token:
                raise SubjectTokenProviderError(
                    "Azure IMDS response did not include an access_token", response=response
                )
            return cast(str, token)
        except Exception as e:
            raise SubjectTokenProviderError(f"Failed to fetch Azure subject token from IMDS: {e}") from e

    return {"token_type": "jwt", "get_token": get_token}


def gcp_id_token_provider(
    audience: str = "https://api.openai.com/v1",
    *,
    timeout: float = 10.0,
    http_client: httpx2.Client | None = None,
) -> SubjectTokenProvider:
    """
    Get a subject token provider for GCP VM instances using the instance metadata server.

    See: https://cloud.google.com/compute/docs/instances/verifying-instance-identity

    Args:
        audience: the unique URI agreed upon by both the instance and the system verifying
            the instance's identity. Defaults to `https://api.openai.com/v1`.

View on GitHub (pinned to 9917c6e28e)

Solutions

  1. Read __cause__ to distinguish connection-refused (not on Azure) from timeout (blocked) from JSON errors (intercepted endpoint)
  2. Only use the Azure provider on Azure compute; for local dev use OPENAI_API_KEY or Azure CLI credentials
  3. Allow egress to 169.254.169.254 in firewall/NetworkPolicy rules
  4. Add graceful degradation: catch SubjectTokenProviderError and fall back to another credential

Example fix

# before
credential = azure_managed_identity_token_provider()  # on laptop -> IMDS unreachable

# after
import os
if os.environ.get("AZURE_MANAGED_IDENTITY"):
    credential = azure_managed_identity_token_provider()
else:
    credential = None  # fall back to OPENAI_API_KEY
Defensive patterns

Strategy: fallback

Validate before calling

import socket
try:
    socket.create_connection(("169.254.169.254", 80), timeout=2)
    imds_reachable = True
except OSError:
    imds_reachable = False

Try / catch

try:
    client = OpenAI(credential=azure_provider())
except SubjectTokenProviderError as e:
    if isinstance(e.__cause__, ConnectionError): client = OpenAI()  # API key fallback

Prevention

When it happens

Trigger: Using azure_managed_identity_token_provider outside Azure (connection refused to IMDS), in environments blocking link-local traffic, with timeouts from network policies, or when the response body isn't valid JSON (json decode error before token extraction).

Common situations: Local development on a laptop with Azure credential configured by mistake; on-prem or other-cloud containers where IMDS doesn't exist; firewall/NetworkPolicy blocking 169.254.169.254; IMDS temporarily unresponsive during Azure maintenance.

Related errors


AI-assisted analysis of openai/openai-python@9917c6e28e (2026-08-28). Data as JSON: /api/errors/084e4e01efb24c06. Report an issue: GitHub.