{"record":{"id":"d989fc5d3df8b8d0","repo":"Significant-Gravitas/AutoGPT","slug":"system-credentials-cannot-be-upgraded","errorCode":null,"errorMessage":"System credentials cannot be upgraded","messagePattern":"System credentials cannot be upgraded","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"error","filePath":"autogpt_platform/backend/backend/api/features/integrations/router.py","lineNumber":968,"sourceCode":"async def _prepare_scope_upgrade(\n    user_id: str,\n    provider: ProviderName,\n    credential_id: str,\n    requested_scopes: list[str],\n) -> list[str]:\n    \"\"\"Validate an existing credential for scope upgrade and compute scopes.\n\n    For providers without native incremental auth (e.g. GitHub), returns the\n    union of existing + requested scopes.  For providers that handle merging\n    server-side (e.g. Google with ``include_granted_scopes``), returns the\n    requested scopes unchanged.\n\n    Raises HTTPException on validation failure.\n    \"\"\"\n    # Platform-owned system credentials must never be upgraded — scope\n    # changes here would leak across every user that shares them.\n    if is_system_credential(credential_id):\n        raise HTTPException(\n            status_code=status.HTTP_400_BAD_REQUEST,\n            detail=\"System credentials cannot be upgraded\",\n        )\n\n    existing = await creds_manager.store.get_creds_by_id(user_id, credential_id)\n    if not existing:\n        raise HTTPException(\n            status_code=status.HTTP_404_NOT_FOUND,\n            detail=\"Credential to upgrade not found\",\n        )\n    if not isinstance(existing, OAuth2Credentials):\n        raise HTTPException(\n            status_code=status.HTTP_400_BAD_REQUEST,\n            detail=\"Only OAuth2 credentials can be upgraded\",\n        )\n    if not provider_matches(existing.provider, provider.value):\n        raise HTTPException(\n            status_code=status.HTTP_400_BAD_REQUEST,","sourceCodeStart":950,"sourceCodeEnd":986,"githubUrl":"https://github.com/Significant-Gravitas/AutoGPT/blob/9c8bb5550f446ba5d3046b78896578742495b3cf/autogpt_platform/backend/backend/api/features/integrations/router.py#L950-L986","documentation":"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'.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Do not target system credentials for upgrade — they are provisioned and rotated by platform operators only.","Filter the credential list before offering upgrade: exclude IDs where is_system_credential(id) is true (they are identifiable by their ID prefix/format).","If broader scopes on a system credential are genuinely needed, request it from the platform operators rather than via the API.","Create a personal (user-owned) credential for the provider and upgrade that instead."],"exampleFix":"# before\nupgrade_target = next(c for c in my_credentials if c.provider == provider)\n\n# after: exclude system credentials from upgrade candidates\nupgrade_target = next(\n    c for c in my_credentials\n    if c.provider == provider and not is_system_credential(c.id)\n)","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"# Exclude system credentials before initiating an upgrade\ndef is_upgradable(cred) -> bool:\n    return cred[\"type\"] == \"oauth2\" and not is_system_credential(cred[\"id\"]) and not cred.get(\"is_managed\")","tryCatchPattern":null,"preventionTips":["Filter system credentials out of any credential picker used for scope upgrades.","Treat system credentials as read-only platform resources.","Unit-test the credential picker against a fixture containing a system credential."],"tags":["oauth","credentials","http-400","system-credential","authorization"],"backgroundTag":null,"analyzedSha":"9c8bb5550f446ba5d3046b78896578742495b3cf","analyzedAt":"2026-08-14T17:17:21.957Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}