Significant-Gravitas/AutoGPT · error · HTTPException

System credentials cannot be upgraded

Error message

System credentials cannot be upgraded

What it means

Raised by _prepare_scope_upgrade when initiating an OAuth scope upgrade for a credential ID that is a platform-owned system credential (is_system_credential(credential_id) is true). System credentials are shared across all users, so letting any user's upgrade flow change their scopes would leak/alter access for everyone. HTTP 400 'System credentials cannot be upgraded'.

Source

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

async def _prepare_scope_upgrade(
    user_id: str,
    provider: ProviderName,
    credential_id: str,
    requested_scopes: list[str],
) -> list[str]:
    """Validate an existing credential for scope upgrade and compute scopes.

    For providers without native incremental auth (e.g. GitHub), returns the
    union of existing + requested scopes.  For providers that handle merging
    server-side (e.g. Google with ``include_granted_scopes``), returns the
    requested scopes unchanged.

    Raises HTTPException on validation failure.
    """
    # Platform-owned system credentials must never be upgraded — scope
    # changes here would leak across every user that shares them.
    if is_system_credential(credential_id):
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="System credentials cannot be upgraded",
        )

    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,

View on GitHub (pinned to 9c8bb5550f)

Solutions

  1. Do not target system credentials for upgrade — they are provisioned and rotated by platform operators only.
  2. Filter the credential list before offering upgrade: exclude IDs where is_system_credential(id) is true (they are identifiable by their ID prefix/format).
  3. If broader scopes on a system credential are genuinely needed, request it from the platform operators rather than via the API.
  4. Create a personal (user-owned) credential for the provider and upgrade that instead.

Example fix

# before
upgrade_target = next(c for c in my_credentials if c.provider == provider)

# after: exclude system credentials from upgrade candidates
upgrade_target = next(
    c for c in my_credentials
    if c.provider == provider and not is_system_credential(c.id)
)
Defensive patterns

Strategy: type-guard

Type guard

# Exclude system credentials before initiating an upgrade
def is_upgradable(cred) -> bool:
    return cred["type"] == "oauth2" and not is_system_credential(cred["id"]) and not cred.get("is_managed")

Prevention

When it happens

Trigger: Calling the OAuth login/upgrade flow (GET /integrations/{provider}/login with an upgrade target) while passing the ID of a system credential — e.g. one provisioned by the platform for managed blocks; frontend state holding a system credential ID from a provider dropdown and submitting it as the upgrade target.

Common situations: UI bug where the credential picker includes system credentials in the upgrade list; scripts that iterate all credentials and try upgrading each; misunderstanding that managed/system connections are read-only for users.

Related errors


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