crewAIInc/crewAI · critical · HTTPException
OIDC not initialized
Error message
OIDC not initialized
What it means
Raised by OIDCAuth.authenticate() when the private _jwk_client attribute is None, meaning the scheme was never initialized with a JWKS endpoint. It returns HTTP 500 because it is an internal state error: the scheme object exists but cannot perform validation. Under normal construction the model validator builds the PyJWKClient from jwks_url, so reaching this branch implies the validator was skipped or the object was mutated.
Source
Thrown at lib/crewai/src/crewai/a2a/auth/server_schemes.py:275
else f"{str(self.issuer).rstrip('/')}/.well-known/jwks.json"
)
self._jwk_client = PyJWKClient(jwks_url, lifespan=self.jwks_cache_ttl)
return self
async def authenticate(self, token: str) -> AuthenticatedUser:
"""Authenticate using OIDC JWT validation.
Args:
token: The JWT to authenticate.
Returns:
AuthenticatedUser on successful authentication.
Raises:
HTTPException: If authentication fails.
"""
if self._jwk_client is None:
raise HTTPException(
status_code=HTTP_500_INTERNAL_SERVER_ERROR,
detail="OIDC not initialized",
)
try:
signing_key = self._jwk_client.get_signing_key_from_jwt(token)
claims = jwt.decode(
token,
signing_key.key,
algorithms=self.algorithms,
audience=self.audience,
issuer=str(self.issuer).rstrip("/"),
leeway=self.clock_skew_seconds,
options={
"require": self.required_claims,
},
)View on GitHub (pinned to 754d7323be)
Solutions
- Construct OIDCAuth with a valid jwks_url so the model validator creates the PyJWKClient: OIDCAuth(jwks_url='https://idp/.well-known/jwks.json', ...).
- Never instantiate the scheme with model_construct(); let pydantic run validators.
- Add a startup assertion that getattr(scheme, '_jwk_client', None) is not None before serving traffic.
- If configuring from discovery documents, fail startup when the discovered jwks_uri is missing.
Example fix
# before
scheme = OIDCAuth.model_construct(issuer="https://idp") # validator skipped, _jwk_client=None
# after
scheme = OIDCAuth(
issuer="https://idp",
jwks_url="https://idp/.well-known/jwks.json",
audience="my-audience",
) Defensive patterns
Strategy: validation
Validate before calling
from crewai.a2a.auth.server_schemes import OIDCAuth
scheme = OIDCAuth(
issuer="https://idp", jwks_url="https://idp/.well-known/jwks.json", audience="api"
)
# smoke check before serving traffic
assert scheme._jwk_client is not None, "OIDCAuth initialized without a JWKS client" Type guard
def is_initialized_oidc(scheme: ServerAuthScheme) -> bool:
"""True when the scheme is an OIDCAuth with a live JWKS client."""
return (
type(scheme).__name__ == "OIDCAuth"
and getattr(scheme, "_jwk_client", None) is not None
) Prevention
- Always construct schemes via normal __init__/model_validate so validators run.
- Never use model_construct() for auth schemes.
- Smoke-test authentication once at startup with a real or dummy token.
When it happens
Trigger: Calling authenticate() on an OIDCAuth instance constructed without a usable jwks_url (or after manually clearing _jwk_client); bypassing pydantic validation via model_construct(); or an OIDC provider that exposes no JWKS URL so initialization silently left the client as None.
Common situations: Building the scheme from a partial dict that omitted jwks_url; using model_construct() or object reuse/copying that skips model_validator(mode='after'); a discovery step that failed upstream and left a half-initialized scheme.
Related errors
- OAuth2 JWKS not initialized
- Unable to fetch signing keys
- OAuth2 introspection not configured
- Token has expired
- Invalid token audience
AI-assisted analysis of crewAIInc/crewAI@754d7323be (2026-08-15).
Data as JSON: /api/errors/9ab56173a4a823a2.
Report an issue: GitHub.