crewAIInc/crewAI · critical · HTTPException
OAuth2 JWKS not initialized
Error message
OAuth2 JWKS not initialized
What it means
Raised by OAuth2ServerAuth._authenticate_jwt() when _jwk_client is None, i.e. the scheme was told to validate JWTs (introspection_url absent or authenticate() routed to _authenticate_jwt) but the JWKS client was never built. It maps to HTTP 500: an internal misconfiguration, not a client fault.
Source
Thrown at lib/crewai/src/crewai/a2a/auth/server_schemes.py:491
to token introspection.
Args:
token: The OAuth2 access token to authenticate.
Returns:
AuthenticatedUser on successful authentication.
Raises:
HTTPException: If authentication fails.
"""
if self._jwk_client:
return await self._authenticate_jwt(token)
return await self._authenticate_introspection(token)
async def _authenticate_jwt(self, token: str) -> AuthenticatedUser:
"""Authenticate using JWKS JWT validation."""
if self._jwk_client is None:
raise HTTPException(
status_code=HTTP_500_INTERNAL_SERVER_ERROR,
detail="OAuth2 JWKS not initialized",
)
try:
signing_key = self._jwk_client.get_signing_key_from_jwt(token)
decode_options: Options = {
"require": self.required_claims,
}
claims = jwt.decode(
token,
signing_key.key,
algorithms=self.algorithms,
audience=self.audience,
issuer=self.issuer,
leeway=self.clock_skew_seconds,View on GitHub (pinned to 754d7323be)
Solutions
- Construct OAuth2ServerAuth normally with jwks_url so the validator initializes _jwk_client.
- Do not use model_construct() or mutate private attrs; rebuild the scheme when config changes.
- Add a startup smoke check: for a JWT-based scheme, assert scheme._jwk_client is not None.
- Recreate the scheme object rather than patching fields after initialization.
Example fix
# before
auth = OAuth2ServerAuth.model_construct(issuer="https://idp") # no jwks client
# after
auth = OAuth2ServerAuth(
issuer="https://idp", audience="api",
jwks_url="https://idp/.well-known/jwks.json",
) Defensive patterns
Strategy: validation
Validate before calling
from crewai.a2a.auth.server_schemes import OAuth2ServerAuth auth = OAuth2ServerAuth(jwks_url="https://idp/.well-known/jwks.json", ...) assert auth._jwk_client is not None, "JWKS client must initialize at construction"
Type guard
def is_jwt_ready(scheme) -> bool:
"""True when the scheme can validate JWTs (has a live JWKS client)."""
return getattr(scheme, "_jwk_client", None) is not None Prevention
- Construct schemes through validated paths only; avoid model_construct().
- Never null out or reassign _jwk_client after construction.
- Add a startup smoke authentication call to catch 500-class misconfigurations early.
When it happens
Trigger: Auth flow reaches _authenticate_jwt() with jwks_url unset — practically only possible when the object bypassed validation (model_construct) or _jwk_client was cleared, because the model validator requires at least one endpoint and builds the client when jwks_url is present.
Common situations: Objects built with model_construct() or copied/reconstructed in a way that skips the model validator; monkeypatched tests that null out _jwk_client; code that swaps config attributes after construction.
Related errors
- OIDC not initialized
- OAuth2 introspection not configured
- Error. A valid pyproject.toml file is required. Check that a
- Error: {e}
- Authorization callback not set. Use set_authorization_callba
AI-assisted analysis of crewAIInc/crewAI@754d7323be (2026-08-15).
Data as JSON: /api/errors/7acba1844997a1d8.
Report an issue: GitHub.