{"record":{"id":"22a4822a6dcd4bbc","repo":"crewAIInc/crewAI","slug":"authorization-callback-not-set-use-set-authorizat","errorCode":null,"errorMessage":"Authorization callback not set. Use set_authorization_callback()","messagePattern":"Authorization callback not set\\. Use set_authorization_callback\\(\\)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"lib/crewai/src/crewai/a2a/auth/client_schemes.py","lineNumber":466,"sourceCode":"        \"\"\"Apply OAuth2 access token to Authorization header.\n\n        Uses asyncio.Lock to ensure only one coroutine handles token operations\n        (initial fetch or refresh) at a time.\n\n        Args:\n            client: HTTP client for making token requests.\n            headers: Current request headers.\n\n        Returns:\n            Updated headers with OAuth2 access token in Authorization header.\n\n        Raises:\n            ValueError: If authorization callback is not set.\n        \"\"\"\n        if self._access_token is None:\n            if self._authorization_callback is None:\n                msg = \"Authorization callback not set. Use set_authorization_callback()\"\n                raise ValueError(msg)\n            async with self._lock:\n                if self._access_token is None:\n                    await self._fetch_initial_token(client)\n        elif self._token_expires_at and time.time() >= self._token_expires_at:\n            async with self._lock:\n                if self._token_expires_at and time.time() >= self._token_expires_at:\n                    await self._refresh_access_token(client)\n\n        if self._access_token:\n            headers[\"Authorization\"] = f\"Bearer {self._access_token}\"\n\n        return headers\n\n    async def _fetch_initial_token(self, client: httpx.AsyncClient) -> None:\n        \"\"\"Fetch initial access token using authorization code flow.\n\n        Args:\n            client: HTTP client for making token request.","sourceCodeStart":448,"sourceCodeEnd":484,"githubUrl":"https://github.com/crewAIInc/crewAI/blob/754d7323beb2fd042e33444a115ea2d5a47193f0/lib/crewai/src/crewai/a2a/auth/client_schemes.py#L448-L484","documentation":"In crewai's A2A OAuth2 client scheme, the Authorization header flow needs a way to obtain the first access token. If no token is cached (_access_token is None) and no authorization callback has been registered via set_authorization_callback(), apply_auth raises ValueError because it has no mechanism to get consent from the user.","triggerScenarios":"Using an OAuth2 client scheme (authorization code flow) for A2A connections and calling the header/auth step before ever calling set_authorization_callback(cb), or after resetting the callback; i.e., first request without prior setup.","commonSituations":"Wiring an agent-to-agent OAuth2 integration and forgetting the interactive consent step; porting from an API-key scheme where no callback was needed; callback set on a different scheme instance than the one used.","solutions":["Register a callback before the first request: scheme.set_authorization_callback(async_callback) where the callback receives the auth URL and returns the authorization code.","Alternatively pre-seed a token if the API supports it, so _access_token is not None on first use.","Make callback registration part of scheme construction in your setup code."],"exampleFix":"# before\nscheme = OAuth2ClientScheme(...)\nawait client.send(request)  # first auth -> ValueError: callback not set\n\n# after\nasync def consent(auth_url: str) -> str:\n    webbrowser.open(auth_url)\n    return input('Paste authorization code: ')\n\nscheme = OAuth2ClientScheme(...)\nscheme.set_authorization_callback(consent)\nawait client.send(request)","handlingStrategy":"validation","validationCode":"scheme = OAuth2ClientScheme(...)\nif scheme._access_token is None and scheme._authorization_callback is None:\n    raise SystemExit('Register a callback: scheme.set_authorization_callback(cb)')","typeGuard":"def oauth2_ready(scheme) -> bool:\n    return getattr(scheme, '_access_token', None) is not None or getattr(scheme, '_authorization_callback', None) is not None","tryCatchPattern":"try:\n    headers = await scheme.apply_auth(client, headers)\nexcept ValueError as e:\n    if 'Authorization callback not set' in str(e):\n        scheme.set_authorization_callback(consent_cb)\n        headers = await scheme.apply_auth(client, headers)\n    else:\n        raise","preventionTips":["Register the authorization callback immediately after constructing the scheme.","Encapsulate scheme setup in a factory that always sets callback or token.","Add a pre-flight check for callback/token before the first A2A request."],"tags":["oauth2","authentication","a2a","configuration"],"backgroundTag":null,"analyzedSha":"754d7323beb2fd042e33444a115ea2d5a47193f0","analyzedAt":"2026-08-15T04:06:56.746Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}