{"record":{"id":"0bb58d5b916dc62f","repo":"Significant-Gravitas/AutoGPT","slug":"picker-tokens-are-not-available-for-provider-pro","errorCode":null,"errorMessage":"Picker tokens are not available for provider '{provider.value}'","messagePattern":"Picker tokens are not available for provider '(.+?)'","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"error","filePath":"autogpt_platform/backend/backend/api/features/integrations/router.py","lineNumber":542,"sourceCode":"        )\n    if not isinstance(credential, OAuth2Credentials):\n        raise HTTPException(\n            status_code=status.HTTP_400_BAD_REQUEST,\n            detail=\"Picker tokens are only available for OAuth2 credentials\",\n        )\n    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","sourceCodeStart":524,"sourceCodeEnd":560,"githubUrl":"https://github.com/Significant-Gravitas/AutoGPT/blob/9c8bb5550f446ba5d3046b78896578742495b3cf/autogpt_platform/backend/backend/api/features/integrations/router.py#L524-L560","documentation":"The picker-token endpoint returns 400 \"Picker tokens are not available for provider '{provider}'\" when the provider is not in _PICKER_TOKEN_ALLOWED_SCOPES. Currently only ProviderName.GOOGLE is allow-listed; the check exists so this bearer-token-minting endpoint cannot be abused for unrelated OAuth integrations (e.g. GitHub).","triggerScenarios":"POST /integrations/github/credentials/<id>/picker-token, or any picker-token call whose path provider is not 'google'.","commonSituations":"Generic client code tries the picker-token endpoint for every provider; a new provider-hosted picker was added frontend-side without allow-listing it backend-side.","solutions":["Only call picker-token for google; for other providers this endpoint is intentionally unavailable","If you genuinely need a new provider-hosted picker, add the provider and its picker scopes to _PICKER_TOKEN_ALLOWED_SCOPES in router.py and ship a backend change — it is a deliberate security gate"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"PICKER_PROVIDERS = {'google'}\nif provider not in PICKER_PROVIDERS:\n    raise ValueError(f'no picker support for {provider}')","typeGuard":"const isPickerProvider = (p: string): boolean => p === 'google';","tryCatchPattern":null,"preventionTips":["Treat picker-token as Google-only unless the backend allow-list says otherwise"],"tags":["picker","allowlist","security","http-400"],"backgroundTag":null,"analyzedSha":"9c8bb5550f446ba5d3046b78896578742495b3cf","analyzedAt":"2026-08-14T17:17:21.957Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}