BerriAI/litellm · error · Exception
Error parsing response: {e}. Check server logs for original
Error message
Error parsing response: {e}. Check server logs for original response. What it means
Raised while fetching JWKS keys in _get_public_key_from_jwks_url: the keys URL answered, but response.json() raised, so the body is not parseable JSON. The full original response text is logged (verbose_proxy_logger.error) but deliberately omitted from the exception; the message tells you to check server logs for it.
Source
Thrown at litellm/proxy/auth/handle_jwt.py:661
litellm_jwtauth: Final = getattr(self, "litellm_jwtauth", None)
if litellm_jwtauth is None:
return 600
return litellm_jwtauth.public_key_ttl
async def _get_public_key_from_jwks_url(self, jwks_url: str, kid: str | None) -> dict:
resolved_jwks_url: Final = await self._resolve_jwks_url(jwks_url)
cache_key: Final = f"litellm_jwt_auth_keys_{resolved_jwks_url}"
cached_keys: Final = await self.user_api_key_cache.async_get_cache(cache_key)
if cached_keys is None:
response: Final = await self.http_handler.get(resolved_jwks_url)
try:
response_json: Final = response.json()
except Exception as e:
verbose_proxy_logger.error("Error parsing response: %s. Original Response: %s", e, response.text)
raise Exception(f"Error parsing response: {e}. Check server logs for original response.")
if "keys" in response_json:
keys: JWKKeyValue = response_json["keys"]
else:
keys = response_json
await self.user_api_key_cache.async_set_cache(
key=cache_key,
value=keys,
ttl=self._get_public_key_cache_ttl(),
)
else:
keys = cached_keys
public_key: Final = self.parse_keys(keys=keys, kid=kid)
if public_key is not None:
return cast(dict, public_key)
View on GitHub (pinned to 77b7c6c40c)
Solutions
- curl the exact JWKS URL from the proxy host and confirm the body is JSON containing keys or a bare JWK
- Check the LiteLLM proxy logs for 'Error parsing response: ... Original Response: ...' to see the actual body that failed to parse
- Make the JWKS endpoint publicly readable (standard OIDC practice) or fix the jwks_uri the discovery document advertises
Defensive patterns
Strategy: validation
Validate before calling
import httpx
async def jwks_url_serves_json(jwks_url: str) -> bool:
async with httpx.AsyncClient() as c:
r = await c.get(jwks_url)
try:
data = r.json()
except ValueError:
return False
return isinstance(data, (dict, list)) Prevention
- Confirm JWKS endpoints are publicly readable (standard OIDC practice) - no auth walls
- Check proxy logs for 'Original Response:' to see the exact non-JSON body when it fires
When it happens
Trigger: The resolved JWKS URL (from jwks_uri or a directly configured JWT_PUBLIC_KEY_URL without the discovery substring) returns HTML or invalid JSON - for example an IdP login page, a WAF block page, or a 200-status error page.
Common situations: JWKS endpoint requires authentication and returns an HTML login form; wrong jwks_uri in a custom IdP; API gateway rewriting /certs to an HTML error page; checking only status codes (200) while the body is HTML.
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.
Related errors
- JWT Auth: OIDC discovery endpoint {url} returned status {res
- JWT Auth: Failed to parse OIDC discovery document at {url}:
- JWT Auth: OIDC discovery document at {url} does not contain
- No matching public key found. keys={resolved_jwks_url}, kid=
- No matching public key found. keys={keys_url_list}, kid={kid
AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18).
Data as JSON: /api/errors/33de90cd662ca49a.
Report an issue: GitHub.