{"record":{"id":"d882f50d891df500","repo":"Significant-Gravitas/AutoGPT","slug":"credential-does-not-grant-any-scope-eligible-for-t","errorCode":null,"errorMessage":"Credential does not grant any scope eligible for the picker. Reconnect with the appropriate scope.","messagePattern":"Credential does not grant any scope eligible for the picker\\. Reconnect with the appropriate scope\\.","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"error","filePath":"autogpt_platform/backend/backend/api/features/integrations/router.py","lineNumber":548,"sourceCode":"    if not credential.access_token:\n        raise HTTPException(\n            status_code=status.HTTP_400_BAD_REQUEST,\n            detail=\"Credential has no access token; reconnect the account\",\n        )\n\n    # Gate on provider+scope: only credentials that actually grant access to\n    # a provider-hosted picker flow may mint a token through this endpoint.\n    # Prevents using this path to extract bearer tokens for unrelated OAuth\n    # integrations (e.g. GitHub) that happen to be stored under the same user.\n    allowed_scopes = _PICKER_TOKEN_ALLOWED_SCOPES.get(provider)\n    if not allowed_scopes:\n        raise HTTPException(\n            status_code=status.HTTP_400_BAD_REQUEST,\n            detail=(f\"Picker tokens are not available for provider '{provider.value}'\"),\n        )\n    cred_scopes = set(credential.scopes or [])\n    if cred_scopes.isdisjoint(allowed_scopes):\n        raise HTTPException(\n            status_code=status.HTTP_400_BAD_REQUEST,\n            detail=(\n                \"Credential does not grant any scope eligible for the picker. \"\n                \"Reconnect with the appropriate scope.\"\n            ),\n        )\n\n    return PickerTokenResponse(\n        access_token=credential.access_token.get_secret_value(),\n        access_token_expires_at=credential.access_token_expires_at,\n    )\n\n\n@router.post(\"/{provider}/credentials\", status_code=201, summary=\"Create Credentials\")\nasync def create_credentials(\n    user_id: Annotated[str, Security(get_user_id)],\n    provider: Annotated[\n        ProviderName, Path(title=\"The provider to create credentials for\")","sourceCodeStart":530,"sourceCodeEnd":566,"githubUrl":"https://github.com/Significant-Gravitas/AutoGPT/blob/9c8bb5550f446ba5d3046b78896578742495b3cf/autogpt_platform/backend/backend/api/features/integrations/router.py#L530-L566","documentation":"The picker-token endpoint returns 400 'Credential does not grant any scope eligible for the picker...' when the credential's granted scopes are disjoint from _PICKER_TOKEN_ALLOWED_SCOPES[provider]. For Google that means the credential holds none of drive.file / drive.readonly / drive. Without one of these the Google Drive Picker cannot read files, so the token mint is refused.","triggerScenarios":"POST picker-token with a Google credential connected with only non-Drive scopes (e.g. gmail or calendar scopes), or a credential whose scopes list came back empty/malformed from the provider.","commonSituations":"User signed in with a narrow scope set for a different feature; app requests incremental scopes and the Drive scope was never granted; scopes stored as a single space-separated string (the Linear quirk handled at line 340) so set intersection fails.","solutions":["Reconnect the Google account requesting a Drive scope: drive.file (per-file, least privilege) or drive.readonly","Pass the scope in the login request so the consent screen prompts for it","Verify afterwards via the credential metadata that the granted scopes now include a Drive scope"],"exampleFix":"// before: login without drive scope\nawait client.post('/integrations/google/login', json={'scopes': ['openid']})\n\n// after: request the picker-eligible scope up front\nawait client.post('/integrations/google/login', json={'scopes': ['https://www.googleapis.com/auth/drive.file']})","handlingStrategy":"validation","validationCode":"PICKER_SCOPES = {\n    'https://www.googleapis.com/auth/drive.file',\n    'https://www.googleapis.com/auth/drive.readonly',\n    'https://www.googleapis.com/auth/drive',\n}\nif not (set(cred_scopes) & PICKER_SCOPES):\n    raise PermissionError('reconnect with a Drive scope before using the picker')","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Request the minimal Drive scope (drive.file) at connect time when the feature uses the picker","Re-check granted scopes after consent — providers can silently drop scopes"],"tags":["picker","oauth2","scopes","google-drive","http-400"],"backgroundTag":null,"analyzedSha":"9c8bb5550f446ba5d3046b78896578742495b3cf","analyzedAt":"2026-08-14T17:17:21.957Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}