Significant-Gravitas/AutoGPT · error · HTTPException

Credential does not grant any scope eligible for the picker.

Error message

Credential does not grant any scope eligible for the picker. Reconnect with the appropriate scope.

What it means

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.

Source

Thrown at autogpt_platform/backend/backend/api/features/integrations/router.py:548

    if not credential.access_token:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="Credential has no access token; reconnect the account",
        )

    # Gate on provider+scope: only credentials that actually grant access to
    # a provider-hosted picker flow may mint a token through this endpoint.
    # Prevents using this path to extract bearer tokens for unrelated OAuth
    # integrations (e.g. GitHub) that happen to be stored under the same user.
    allowed_scopes = _PICKER_TOKEN_ALLOWED_SCOPES.get(provider)
    if not allowed_scopes:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=(f"Picker tokens are not available for provider '{provider.value}'"),
        )
    cred_scopes = set(credential.scopes or [])
    if cred_scopes.isdisjoint(allowed_scopes):
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=(
                "Credential does not grant any scope eligible for the picker. "
                "Reconnect with the appropriate scope."
            ),
        )

    return PickerTokenResponse(
        access_token=credential.access_token.get_secret_value(),
        access_token_expires_at=credential.access_token_expires_at,
    )


@router.post("/{provider}/credentials", status_code=201, summary="Create Credentials")
async def create_credentials(
    user_id: Annotated[str, Security(get_user_id)],
    provider: Annotated[
        ProviderName, Path(title="The provider to create credentials for")

View on GitHub (pinned to 9c8bb5550f)

Solutions

  1. Reconnect the Google account requesting a Drive scope: drive.file (per-file, least privilege) or drive.readonly
  2. Pass the scope in the login request so the consent screen prompts for it
  3. Verify afterwards via the credential metadata that the granted scopes now include a Drive scope

Example fix

// before: login without drive scope
await client.post('/integrations/google/login', json={'scopes': ['openid']})

// after: request the picker-eligible scope up front
await client.post('/integrations/google/login', json={'scopes': ['https://www.googleapis.com/auth/drive.file']})
Defensive patterns

Strategy: validation

Validate before calling

PICKER_SCOPES = {
    'https://www.googleapis.com/auth/drive.file',
    'https://www.googleapis.com/auth/drive.readonly',
    'https://www.googleapis.com/auth/drive',
}
if not (set(cred_scopes) & PICKER_SCOPES):
    raise PermissionError('reconnect with a Drive scope before using the picker')

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of Significant-Gravitas/AutoGPT@9c8bb5550f (2026-08-14). Data as JSON: /api/errors/d882f50d891df500. Report an issue: GitHub.