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

  1. curl the exact JWKS URL from the proxy host and confirm the body is JSON containing keys or a bare JWK
  2. Check the LiteLLM proxy logs for 'Error parsing response: ... Original Response: ...' to see the actual body that failed to parse
  3. 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

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


AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18). Data as JSON: /api/errors/33de90cd662ca49a. Report an issue: GitHub.