openai/openai-python · critical · SubjectTokenProviderError

Azure IMDS response did not include an access_token

Error message

Azure IMDS response did not include an access_token

What it means

IMDS returned HTTP success but the JSON body either lacked an access_token key or contained a falsy value. This means the metadata endpoint is reachable (often a proxy or a misrouted 169.254.169.254 answering) but is not returning a genuine Azure IMDS token payload — the provider treats it as an authentication failure rather than sending an invalid token upstream.

Source

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

                params["client_id"] = client_id
            if msi_res_id is not None:
                params["msi_res_id"] = msi_res_id

            if http_client is not None:
                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.

View on GitHub (pinned to 9917c6e28e)

Solutions

  1. Verify what actually answers: curl http://169.254.169.254/metadata/identity/oauth2/token?... from the same network namespace
  2. Disable/adjust proxies and network policies so link-local metadata traffic reaches real Azure IMDS (NO_PROXY=169.254.169.254)
  3. If not on Azure, use the correct provider for your platform (GCP metadata, k8s workload identity, or API key)
  4. Attach and inspect the response on the error object to see the unexpected payload

Example fix

# before
export HTTP_PROXY=http://proxy:3128  # proxy intercepts 169.254.169.254

# after
export NO_PROXY=169.254.169.254
export HTTP_PROXY=http://proxy:3128
Defensive patterns

Strategy: fallback

Validate before calling

import httpx, json
r = httpx.get(IMDS_URL, headers={"Metadata":"true"})
assert "access_token" in r.json(), r.text[:200]

Try / catch

try:
    token = get_token()
except SubjectTokenProviderError as e:
    token = fallback_credential()  # e.g. env API key / Azure CLI

Prevention

When it happens

Trigger: Success-status responses from something impersonating IMDS: cloud-proxied metadata endpoints, container network setups that intercept link-local addresses, or environments (e.g. non-Azure clouds/VMs with fake IMDS) returning JSON without access_token; also Azure environments in an unusual state returning error JSON with 200.

Common situations: Running in Docker/K8s where 169.254.169.254 is NAT'd to another service; localhost proxies answering all routes with 200; middleware appliances; misconfigured Azure Stack/sovereign cloud endpoints.

Related errors


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