PrefectHQ/fastmcp · error · ValueError
JWKS URI not configured
Error message
JWKS URI not configured
What it means
This error means the JWT verification provider was asked to verify a token but its JWKS URI — the URL of the identity provider's JSON Web Key Set — was never set. The library throws it from _get_jwks_key because without a JWKS URI there is no way to fetch the public key needed to verify the token's signature. It is a configuration error in the provider, not a token problem.
Source
Thrown at fastmcp_slim/fastmcp/server/auth/providers/jwt.py:348
async def _get_verification_key(self, token: str) -> str | bytes:
"""Get the verification key for the token."""
if self.public_key:
return self.public_key
# Extract kid from token header for JWKS lookup
try:
header = decode_jwt_header(token)
kid = header.get("kid")
return await self._get_jwks_key(kid)
except (ValueError, KeyError, IndexError, json.JSONDecodeError) as e:
raise ValueError(f"Failed to extract key ID from token: {e}") from e
async def _get_jwks_key(self, kid: str | None) -> str:
"""Fetch key from JWKS with simple caching and SSRF protection."""
if not self.jwks_uri:
raise ValueError("JWKS URI not configured")
current_time = time.time()
# Check cache first
if current_time - self._jwks_cache_time < self._cache_ttl:
if kid and kid in self._jwks_cache:
return self._jwks_cache[kid]
elif not kid and len(self._jwks_cache) == 1:
# If no kid but only one key cached, use it
return next(iter(self._jwks_cache.values()))
# Fetch JWKS — with SSRF protection when enabled (untrusted URIs)
try:
jwks_data = await self._fetch_jwks()
# Cache all usable keys. A key that cannot be converted is skipped
# rather than failing the whole set — per RFC 7517 §5, clients
# should ignore JWKs they don't understand. Otherwise one exoticView on GitHub (pinned to 1f02114297)
Solutions
- Set jwks_uri in the verifier config to your identity provider's JWKS endpoint (e.g. https://idp.example.com/.well-known/jwks.json or the /.well-known/openid-configuration jwks_uri value)
- Verify the config source: if jwks_uri comes from an env var or settings file, confirm it is populated and non-empty at startup
- If you intend asymmetric verification, either provide jwks_uri or a static public_key/secret_key — one of them must be configured
- Add a startup validation that instantiates the verifier and checks jwks_uri before the server accepts traffic
Example fix
// before
verifier = JWTVerifier(issuer="https://idp.example.com")
// after
verifier = JWTVerifier(
issuer="https://idp.example.com",
jwks_uri="https://idp.example.com/.well-known/jwks.json",
) Defensive patterns
Strategy: validation
Validate before calling
if not getattr(verifier, "jwks_uri", None):
raise RuntimeError("JWTVerifier requires a jwks_uri for asymmetric verification") Type guard
def has_jwks_uri(v) -> bool:
return bool(getattr(v, "jwks_uri", None)) Try / catch
try:
claims = await verifier.verify_token(token)
except ValueError as e:
if "JWKS URI not configured" in str(e):
# misconfiguration: fix server config, do not retry
raise RuntimeError("JWT verifier misconfigured: set jwks_uri") from e
raise Prevention
- Assert jwks_uri (or a static key) is set when constructing the verifier at startup
- Validate config in unit tests: instantiate the verifier from your settings object and check jwks_uri
- Fail fast with a health check that hits verify_token with a dummy token at boot
When it happens
Trigger: Calling verify_token (via _get_verification_key -> _get_jwks_key) on a JWTVerifier/TokenVerifier instance constructed without a jwks_uri, or where the jwks_uri argument was None/empty string.
Common situations: Constructing the verifier programmatically and omitting jwks_uri while also omitting secret_key/public_key; env-driven config where the JWKS variable is unset or empty; copying a verifier config that only specified an issuer; switching from a static-key verifier to a JWKS verifier without moving the URL over.
Related errors
- No keys found in JWKS
- Invalid token issuer
- Invalid token audience
- Key ID '{kid}' found in JWKS but its key type is unsupported
- Key ID '{kid}' not found in JWKS
AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29).
Data as JSON: /api/errors/75dc659e6221cfe4.
Report an issue: GitHub.