crewAIInc/crewAI · error · ValueError
Authorization callback not set
Error message
Authorization callback not set
What it means
In the OAuth2 authorization-code flow of crewai's A2A client, _fetch_initial_token builds the consent URL and must hand it to the user via the registered callback to obtain an authorization code. If set_authorization_callback() was never called, the token exchange cannot even start and raises ValueError('Authorization callback not set').
Source
Thrown at lib/crewai/src/crewai/a2a/auth/client_schemes.py:500
Args:
client: HTTP client for making token request.
Raises:
ValueError: If authorization callback is not set.
httpx.HTTPStatusError: If token request fails.
"""
params = {
"response_type": "code",
"client_id": self.client_id,
"redirect_uri": self.redirect_uri,
"scope": " ".join(self.scopes),
}
auth_url = f"{self.authorization_url}?{urllib.parse.urlencode(params)}"
if self._authorization_callback is None:
msg = "Authorization callback not set"
raise ValueError(msg)
auth_code = await self._authorization_callback(auth_url)
data = {
"grant_type": "authorization_code",
"code": auth_code,
"client_id": self.client_id,
"client_secret": self.client_secret,
"redirect_uri": self.redirect_uri,
}
response = await client.post(self.token_url, data=data)
response.raise_for_status()
token_data = response.json()
self._access_token = token_data["access_token"]
self._refresh_token = token_data.get("refresh_token")
expires_in = token_data.get("expires_in", 3600)View on GitHub (pinned to 754d7323be)
Solutions
- Call scheme.set_authorization_callback(callback) before the first authenticated request.
- For headless flows, implement a callback that logs the URL and reads the code from a queue/file.
- If interactive consent is not possible, switch to a client-credentials or API-key scheme instead of authorization_code.
Example fix
# before
response = await client.fetch_token(...) # _authorization_callback None -> ValueError
# after
async def get_code(url: str) -> str:
print('Visit:', url)
return input('Code: ')
scheme.set_authorization_callback(get_code)
response = await client.fetch_token(...) Defensive patterns
Strategy: validation
Validate before calling
scheme = OAuth2ClientScheme(...)
if getattr(scheme, '_authorization_callback', None) is None:
raise SystemExit('OAuth2 code flow needs set_authorization_callback() before first token fetch') Type guard
def has_auth_callback(scheme) -> bool:
return getattr(scheme, '_authorization_callback', None) is not None Try / catch
try:
await scheme._fetch_initial_token(client)
except ValueError as e:
if 'Authorization callback not set' in str(e):
scheme.set_authorization_callback(consent)
await scheme._fetch_initial_token(client)
else:
raise Prevention
- Wire the consent callback at construction time, not lazily at request time.
- For headless services, prefer a scheme that does not need user consent (client credentials/API key).
- Test the OAuth2 happy path in CI with a stub callback to catch setup-order bugs.
When it happens
Trigger: Triggering the initial token fetch (no cached access token) on an OAuth2ClientScheme whose _authorization_callback is None - typically the first authentication attempt after object creation without setup.
Common situations: Automated/headless A2A clients where nobody wired a consent callback; refactors that construct the scheme in a different place than where the callback was registered; assuming client_credentials behavior from an authorization_code scheme.
Related errors
- Error. A valid pyproject.toml file is required. Check that a
- Error: {e}
- Authorization callback not set. Use set_authorization_callba
- Project name cannot be empty or contain only whitespace
- Project name '{name}' contains no valid characters for a Pyt
AI-assisted analysis of crewAIInc/crewAI@754d7323be (2026-08-15).
Data as JSON: /api/errors/f470fc5190a14582.
Report an issue: GitHub.