crewAIInc/crewAI · error · ValueError
Either jwks_url or introspection_url must be provided for to
Error message
Either jwks_url or introspection_url must be provided for token validation
What it means
A pydantic ValidationError raised inside OAuth2ServerAuth's model_validator(mode='after') when the configuration provides neither jwks_url nor introspection_url. The scheme refuses to construct because it would have no way to validate tokens. It surfaces at configuration time (startup), not per request.
Source
Thrown at lib/crewai/src/crewai/a2a/auth/server_schemes.py:451
)
jwks_cache_ttl: int = Field(
default=3600,
description="TTL for JWKS cache in seconds",
ge=60,
)
clock_skew_seconds: float = Field(
default=30.0,
description="Allowed clock skew for token validation",
ge=0.0,
)
_jwk_client: PyJWKClient | None = PrivateAttr(default=None)
@model_validator(mode="after")
def _validate_and_init(self) -> Self:
"""Validate configuration and initialize JWKS client if needed."""
if not self.jwks_url and not self.introspection_url:
raise ValueError(
"Either jwks_url or introspection_url must be provided for token validation"
)
if self.introspection_url:
if not self.introspection_client_id or not self.introspection_client_secret:
raise ValueError(
"introspection_client_id and introspection_client_secret are required "
"when using token introspection"
)
if self.jwks_url:
self._jwk_client = PyJWKClient(
str(self.jwks_url), lifespan=self.jwks_cache_ttl
)
return self
async def authenticate(self, token: str) -> AuthenticatedUser:View on GitHub (pinned to 754d7323be)
Solutions
- Provide at least one validation endpoint: OAuth2ServerAuth(jwks_url='https://idp/.well-known/jwks.json', ...) for JWTs.
- For opaque tokens, provide introspection_url plus introspection_client_id and introspection_client_secret.
- Validate the config at startup and log which fields are missing instead of discovering it via the traceback.
- If both are configured, ensure at least one URL is reachable before going live.
Example fix
# before
auth = OAuth2ServerAuth(issuer="https://idp", audience="api") # ValidationError
# 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
# fails fast with a clear pydantic error instead of at request time
auth = OAuth2ServerAuth(
jwks_url="https://idp/.well-known/jwks.json", # or introspection_url + credentials
) Try / catch
try:
auth = OAuth2ServerAuth(**cfg)
except ValidationError as e:
if "jwks_url or introspection_url" in str(e):
cfg.setdefault("jwks_url", os.environ["JWKS_URL"]) # supply the missing endpoint
auth = OAuth2ServerAuth(**cfg) Prevention
- Always pass exactly one of jwks_url (JWTs) or introspection_url (opaque tokens).
- Validate auth config during startup, not lazily on first request.
- Use pydantic model_validate on config dicts to surface all errors at once.
When it happens
Trigger: Instantiating OAuth2ServerAuth() with only issuer/audience fields and no validation endpoint: OAuth2ServerAuth(issuer='https://idp', audience='api') raises immediately; or a config dict built from env vars where both JWKS_URL and INTROSPECTION_URL are empty strings.
Common situations: Copy-pasting an OIDCAuth config into OAuth2ServerAuth and dropping jwks_url; env-var-driven configs where the variable name changed between versions; partially filled YAML config files.
Related errors
- introspection_client_id and introspection_client_secret are
- return_columns cannot be empty. At least one column must be
- Invalid configuration for embedding provider '{provider}':\n
- Authorization callback not set. Use set_authorization_callba
- Error. A valid pyproject.toml file is required. Check that a
AI-assisted analysis of crewAIInc/crewAI@754d7323be (2026-08-15).
Data as JSON: /api/errors/a2e067c287f73e3d.
Report an issue: GitHub.