BerriAI/litellm · critical · Exception

Missing JWT Public Key URL from environment.

Error message

Missing JWT Public Key URL from environment.

What it means

Raised at the top of get_public_key in litellm/proxy/auth/handle_jwt.py: the JWT authentication path was invoked (a bearer JWT arrived and JWT auth is enabled) but the JWT_PUBLIC_KEY_URL environment variable is not set, so there is nowhere to fetch verification keys from. Every JWT-authenticated request fails until it is configured.

Source

Thrown at litellm/proxy/auth/handle_jwt.py:686

            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)

        raise NoMatchingJWTPublicKeyError(f"No matching public key found. keys={resolved_jwks_url}, kid={kid}")

    async def get_public_key(self, kid: str | None) -> dict:
        keys_url: Final = os.getenv("JWT_PUBLIC_KEY_URL")

        if keys_url is None:
            raise Exception("Missing JWT Public Key URL from environment.")

        keys_url_list: Final = [url.strip() for url in keys_url.split(",") if url.strip()]

        for key_url in keys_url_list:
            try:
                return await self._get_public_key_from_jwks_url(jwks_url=key_url, kid=kid)
            except NoMatchingJWTPublicKeyError as e:
                verbose_proxy_logger.debug("JWT Auth: No matching public key found at %s: %s", key_url, e)

        raise NoMatchingJWTPublicKeyError(f"No matching public key found. keys={keys_url_list}, kid={kid}")

    def parse_keys(self, keys: JWKKeyValue, kid: str | None) -> JWTKeyItem | None:
        public_key: JWTKeyItem | None = None
        if len(keys) == 1:
            if isinstance(keys, dict) and (keys.get("kid", None) == kid or kid is None):
                public_key = keys
            elif isinstance(keys, list) and (keys[0].get("kid", None) == kid or kid is None):
                public_key = keys[0]

View on GitHub (pinned to 77b7c6c40c)

Solutions

  1. Set JWT_PUBLIC_KEY_URL in the proxy's environment to your JWKS or OIDC discovery URL
  2. Alternatively configure the public key statically in the config YAML under litellm_settings.litellm_jwtauth (JWT_PUBLIC_KEY / public key fields) so the env lookup path is not needed
  3. Verify with a printout at startup (e.g. echo in the entrypoint) that the variable is actually exported in the container running the proxy

Example fix

# before: container started without the variable
docker run litellm/litellm --config /config.yaml

# after: pass the JWKS URL
docker run -e JWT_PUBLIC_KEY_URL=https://idp.example.com/protocol/openid-connect/certs litellm/litellm --config /config.yaml
Defensive patterns

Strategy: validation

Validate before calling

import os, sys

required = "JWT_PUBLIC_KEY_URL"
if not os.getenv(required):
    sys.exit(f"missing required env var {required} for JWT auth - set it to your JWKS/discovery URL")

Prevention

When it happens

Trigger: Client sends Authorization: Bearer <jwt> to a proxy configured for JWT auth, but the deployment never set JWT_PUBLIC_KEY_URL (env var or its config equivalent), so get_public_key raises immediately.

Common situations: Docker/Kubernetes deployment where the env var is missing from the manifest or secret; config migrated from static JWT_PUBLIC_KEY to JWKS-based auth without adding the URL; CI/local environment diverging from prod env setup.

Understand the failure class

Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.

Related errors


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