crewAIInc/crewAI · error · SystemExit
Error. A valid pyproject.toml file is required. Check that a
Error message
Error. A valid pyproject.toml file is required. Check that a valid pyproject.toml file exists in the current directory.
What it means
Raised as an HTTP 503 when an A2A server using OAuth2ServerAuth with an introspection_url cannot complete RFC 7662 token introspection. The introspection endpoint returned an HTTP error or the request failed unexpectedly (network error, timeout, bad credentials, malformed JSON). The server deliberately maps infrastructure failures to 503 instead of 401 to distinguish 'token bad' from 'cannot verify token'.
Source
Thrown at lib/cli/src/crewai_cli/cli.py:118
@click.group()
@click.version_option(_get_cli_version())
def crewai() -> None:
"""Top-level command group for crewai."""
@crewai.command(
name="uv",
context_settings={"ignore_unknown_options": True},
)
@click.argument("uv_args", nargs=-1, type=click.UNPROCESSED)
def uv(uv_args: tuple[str, ...]) -> None:
"""A wrapper around uv commands that adds custom tool authentication through env vars."""
try:
read_toml()
except FileNotFoundError as e:
raise SystemExit(
"Error. A valid pyproject.toml file is required. Check that a valid pyproject.toml file exists in the current directory."
) from e
except Exception as e:
raise SystemExit(f"Error: {e}") from e
env = build_env_with_all_tool_credentials()
try:
subprocess.run( # noqa: S603
["uv", *uv_args], # noqa: S607
capture_output=False,
env=env,
text=True,
check=True,
)
except subprocess.CalledProcessError as e:
click.secho(f"uv command failed with exit code {e.returncode}", fg="red")
raise SystemExit(e.returncode) from eView on GitHub (pinned to 754d7323be)
Solutions
- Verify the introspection endpoint is reachable from the server host: curl -u client_id:client_secret -d 'token=<tok>' <introspection_url> and confirm a 200 with JSON containing "active"
- Check introspection_client_id and introspection_client_secret match credentials registered with the IdP (most IdPs require basic auth on the introspection endpoint)
- Confirm introspection_url is a fully qualified https URL to the RFC 7662 endpoint (e.g. https://idp.example.com/oauth2/introspect, not the token or userinfo endpoint)
- Inspect server logs: the 'OAuth2 introspection failed' log record includes reason (http_error vs unexpected_error), status_code, and error text pinpointing the layer that failed
- If failures are transient (IdP briefly restarting), treat 503 as retryable on the client side with backoff
Example fix
# before
OAuth2ServerAuth(
introspection_url="https://idp.example.com/oauth2/introspect", # wrong creds / endpoint
)
# after
OAuth2ServerAuth(
introspection_url="https://idp.example.com/oauth2/introspect",
introspection_client_id="my-client",
introspection_client_secret=SecretStr(os.environ["INTROSPECTION_SECRET"]), # verified via curl first
) Defensive patterns
Strategy: retry
Validate before calling
import httpx
async def introspection_endpoint_healthy(url: str, client_id: str, client_secret: str) -> bool:
try:
async with httpx.AsyncClient(timeout=5) as c:
r = await c.post(url, data={"token": "healthcheck-dummy"}, auth=(client_id, client_secret))
return r.status_code == 200 and isinstance(r.json(), dict)
except httpx.HTTPError:
return False Try / catch
from fastapi import HTTPException
try:
user = await scheme.authenticate(request)
except HTTPException as e:
if e.status_code == 503: # introspection unavailable -> retryable
raise RetryableUpstreamError("IdP introspection down") from e
raise # 401s are not retryable Prevention
- Monitor the introspection endpoint with a health check and alert before it breaks auth
- Store introspection client credentials in a secret manager and rotate them with the server config, never hardcode
- Set explicit httpx timeouts on outbound IdP calls so hung endpoints fail fast instead of piling up
- Distinguish 503 (retry later) from 401 (fix token) in client error handling
When it happens
Trigger: Calling an A2A endpoint protected by OAuth2ServerAuth configured with introspection_url while: the identity provider is down or unreachable; introspection_client_id/secret are wrong so the IdP returns 4xx; the URL is misconfigured (DNS failure, TLS error, non-HTTP2 JSON body); or httpx raises any non-HTTPStatusError exception (connect timeout, ReadTimeout) inside _authenticate_introspection (server_schemes.py:587-619).
Common situations: IdP outage or maintenance window; introspection endpoint behind a VPN/firewall the server cannot reach; client credentials rotated but the CrewAI auth config was not updated; typo in introspection_url; self-signed certificate rejected by httpx.
Related errors
- Token introspection service unavailable
- Error: {e}
- Authorization callback not set. Use set_authorization_callba
- Authorization callback not set
- Unable to fetch signing keys
AI-assisted analysis of crewAIInc/crewAI@754d7323be (2026-08-15).
Data as JSON: /api/errors/3ea919e2876fe96a.
Report an issue: GitHub.