Significant-Gravitas/AutoGPT · warning · HTTPException
Managed credentials cannot be upgraded
Error message
Managed credentials cannot be upgraded
What it means
In _prepare_scope_upgrade, if the existing OAuth2 credential has is_managed=True (provisioned and governed by an external identity/secret manager rather than the user), HTTP 400 'Managed credentials cannot be upgraded' is raised. Managed credentials are lifecycle-controlled by the managing system; user-initiated scope merges could desync the manager's state or grant scopes the manager did not approve.
Source
Thrown at autogpt_platform/backend/backend/api/features/integrations/router.py:990
existing = await creds_manager.store.get_creds_by_id(user_id, credential_id)
if not existing:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Credential to upgrade not found",
)
if not isinstance(existing, OAuth2Credentials):
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Only OAuth2 credentials can be upgraded",
)
if not provider_matches(existing.provider, provider.value):
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Credential provider does not match the requested provider",
)
if existing.is_managed:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Managed credentials cannot be upgraded",
)
# Google handles scope merging via include_granted_scopes; others need
# the union of existing + new scopes in the login URL.
if provider != ProviderName.GOOGLE:
requested_scopes = list(set(requested_scopes) | set(existing.scopes))
return requested_scopes
async def _merge_or_create_credential(
user_id: str,
provider: ProviderName,
credentials: OAuth2Credentials,
credential_id: str | None,
) -> OAuth2Credentials:View on GitHub (pinned to 9c8bb5550f)
Solutions
- Exclude is_managed credentials from upgrade actions in the UI/API calls.
- To get more scopes, create a personal OAuth connection for the provider instead of touching the managed one.
- If the managed credential genuinely needs new scopes, update it through the managing system (the secret manager / provisioning pipeline), not the user upgrade API.
Example fix
# before eligible = [c for c in creds if c.provider == provider] # after eligible = [c for c in creds if c.provider == provider and not c.is_managed]
Defensive patterns
Strategy: type-guard
Type guard
def can_upgrade(cred: dict) -> bool:
return cred["type"] == "oauth2" and not cred.get("is_managed") and not is_system_credential(cred["id"]) Prevention
- Hide upgrade actions for managed credentials.
- Know your deployment: check is_managed when listing credentials.
When it happens
Trigger: Initiating scope upgrade on a credential flagged is_managed — e.g. enterprise-deployed credentials distributed to users via a secret manager integration; attempting to upgrade via the login URL with upgrade_credentials_id pointing at a managed credential.
Common situations: Enterprise/shared deployments where some connections are provisioned centrally; UI not distinguishing managed vs personal credentials in the upgrade flow.
Related errors
- System credentials cannot be upgraded
- Only OAuth2 credentials can be upgraded
- Credential provider does not match the requested provider
- Username mismatch: authenticated as a different user
- Server did not return an access token for the Google Drive p
AI-assisted analysis of Significant-Gravitas/AutoGPT@9c8bb5550f (2026-08-14).
Data as JSON: /api/errors/4ba6e112b5fe364e.
Report an issue: GitHub.