BerriAI/litellm · error · Exception
JWT Auth: Failed to parse OIDC discovery document at {url}:
Error message
JWT Auth: Failed to parse OIDC discovery document at {url}: {e} What it means
Raised in _resolve_jwks_url when the OIDC discovery endpoint returned HTTP 200 but response.json() failed - the body is not valid JSON. The original parse error is chained into the message. This means the URL resolved and answered, but what it returned is not a discovery document.
Source
Thrown at litellm/proxy/auth/handle_jwt.py:628
"""
if ".well-known/openid-configuration" not in url:
return url
cache_key: Final = f"litellm_oidc_discovery_{url}"
cached_jwks_uri: Final = await self.user_api_key_cache.async_get_cache(cache_key)
if cached_jwks_uri is not None:
return cached_jwks_uri
verbose_proxy_logger.debug("JWT Auth: Fetching OIDC discovery document from %s", url)
response: Final = await self.http_handler.get(url)
if response.status_code != 200:
raise Exception(
f"JWT Auth: OIDC discovery endpoint {url} returned status {response.status_code}: {response.text}"
)
try:
discovery: Final = response.json()
except Exception as e:
raise Exception(f"JWT Auth: Failed to parse OIDC discovery document at {url}: {e}")
jwks_uri: Final = discovery.get("jwks_uri")
if not jwks_uri:
raise Exception(f"JWT Auth: OIDC discovery document at {url} does not contain a 'jwks_uri' field.")
verbose_proxy_logger.debug("JWT Auth: Resolved OIDC discovery %s -> jwks_uri=%s", url, jwks_uri)
await self.user_api_key_cache.async_set_cache(
key=cache_key,
value=jwks_uri,
ttl=self._get_public_key_cache_ttl(),
)
return jwks_uri
def _get_public_key_cache_ttl(self) -> float:
litellm_jwtauth: Final = getattr(self, "litellm_jwtauth", None)
if litellm_jwtauth is None:
return 600
return litellm_jwtauth.public_key_ttlView on GitHub (pinned to 77b7c6c40c)
Solutions
- curl -s <url> | python -m json.tool from the proxy host to see the raw body and where JSON parsing fails
- If HTML comes back, the URL is being intercepted - use the true IdP discovery URL or the JWKS URL directly
- Ensure the fetch is unauthenticated (no auth wall) or whitelist the proxy's egress for that host
Example fix
# before: URL that returns an HTML login page with 200 JWT_PUBLIC_KEY_URL=https://sso.example.com/.well-known/openid-configuration # after: the IdP's real discovery endpoint (or direct JWKS URL) JWT_PUBLIC_KEY_URL=https://idp.example.com/oidc/realms/prod/.well-known/openid-configuration
Defensive patterns
Strategy: validation
Validate before calling
import httpx
async def discovery_returns_json(url: str) -> bool:
async with httpx.AsyncClient() as c:
r = await c.get(url)
if r.status_code != 200:
return False
try:
r.json()
return True
except ValueError:
return False # HTML login/block page served with 200 Prevention
- Smoke-test IdP endpoints with curl and inspect the body, not just the status code
- Watch for SSO gateways that answer 200 with HTML for unauthenticated clients
- Point JWT_PUBLIC_KEY_URL at the direct JWKS URL when discovery is unreliable
When it happens
Trigger: JWT_PUBLIC_KEY_URL contains .well-known/openid-configuration and the server responds 200 with HTML (a login page, an SPA shell, a proxy block page) or truncated/invalid JSON, so json decoding raises.
Common situations: A gateway/SSO portal in front of the IdP serving an HTML page for unauthenticated fetchers; a typo'd URL that matches some catch-all route returning 200 HTML; response corruption through a corporate proxy.
Understand the failure class
Background: "Invalid JSON response" and "Failed to parse response" errors: when an API answers 200 but the body isn't the JSON your library expected — this error's family across 28 libraries.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- JWT Auth: OIDC discovery endpoint {url} returned status {res
- JWT Auth: OIDC discovery document at {url} does not contain
- Error parsing response: {e}. Check server logs for original
- OIDC UserInfo endpoint not configured. Set 'oidc_userinfo_en
- MCPJWTSigner: access_token_discovery_uri discovery document
AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18).
Data as JSON: /api/errors/58c208bf715e0067.
Report an issue: GitHub.