# Error codes: accounts and sessions

The codes of the Identity and Sessions areas: user accounts, operator accounts, API keys, connected applications, SCIM tokens, device accounts, sign-in, second factor, refresh, and impersonation.

> **Type:** reference
> **For:** Anyone who manages accounts or keys through the API or builds a sign-in.
> **Prerequisite:** know the error format — see [The error format](/api/error-format)

## How to read the tables

Read the tables like this: **Code** is the value of the `code` field in the error body. Your logic switches on it, never on `message`. **Meaning** and **Typical trigger** classify the case. **HTTP** is the status actually sent. **Expected reaction** is your client’s response, drawn from a fixed vocabulary that is the same on all seven error-code pages: “check credentials” (401), “check permission or package” (402, 403), “correct the input” (400, 413, 415, 422), “reload, resend” (version conflicts), “do not retry, check the operation” (404, 409, 410, 426), “wait (Retry-After)” (429), and “retry later, report the trace ID if it recurs” (5xx).

## The codes

### Accounts, keys, devices (Identity)

Accounts, operator accounts, API keys, and devices. For integrations, the key codes are the most important. `ApiKey.ScopeEscalationBlocked` (403) means the key asks for more than its creator is allowed to do. `ApiKey.ScopeNotKeyCapable` (422) means a chosen permission is not intended for keys, and asking does not help here, only a different approach. Two more are `ApiKey.ExpiresAtInPast` (422) and `ApiKey.AlreadyRevoked` (409), because revocation is final. The `OperatorApiKey.*` codes concern operator keys (`opk_`). Then there are the forms of access that are not tied to a person: `OAuthClient.*` and `OAuthAuthorization.*` for [connected applications](/api/oauth-delegated-access). `OAuthAuthorization.Expired` (410) and `OAuthAuthorization.AlreadyDecided` (409) are the ones you will see most often, and both mean “restart the consent”. Finally, `ScimToken.*` covers the access with which a staff directory [syncs accounts](/api/scim-provisioning). Among the `Device.*` codes, `Device.Blocked` (409) rejects a blocked device until the operator lifts the block.

| Code | Meaning | Typical trigger | HTTP | Expected reaction |
|---|---|---|---|---|
| `User.NotFound` | Account not found | Access to an unknown account ID | 404 | do not retry, check the operation |
| `User.EmailAlreadyExists` | Email already taken | Creation with an address that is already in use | 409 | do not retry, check the operation |
| `User.PlanSeatQuotaExceeded` | Seat limit reached | Account over the seat limit of the package | 422 | correct the input |
| `User.MissingCredential` | Sign-in credentials missing | Account with neither a password nor a company sign-in | 422 | correct the input |
| `User.SsoInconsistent` | Company sign-in state inconsistent | Contradictory link to the company sign-in | 422 | correct the input |
| `User.SsoUnlinkRequiresPassword` | Unlinking the sign-in requires a password | Unlinking without a password set | 422 | correct the input |
| `User.CurrentPasswordMismatch` | Current password incorrect | Password change with the wrong current password | 400 | correct the input |
| `User.PasswordAlreadySet` | Password already set | First password for an account that already has one | 409 | do not retry, check the operation |
| `User.RoleEscalationBlocked` | Permission escalation blocked | Assigning higher permissions than your own | 403 | check permission or package |
| `User.LastRoleRemovalBlocked` | Last role cannot be removed | Demoting the last Owner | 409 | do not retry, check the operation |
| `User.RoleRequired` | Role is required | Assignment without a role — an account has exactly one | 422 | correct the input |
| `User.MultipleRolesNotAllowed` | More than one role | Assignment with several roles | 422 | correct the input |
| `User.LastOwnerSuspensionBlocked` | Last Owner cannot be suspended | Suspending the only active Owner | 409 | do not retry, check the operation |
| `User.CannotSuspendSelf` | Self-suspension blocked | Suspending your own account | 403 | check permission or package |
| `User.CannotModifySelf` | Own role cannot be changed | Role change on your own account | 403 | check permission or package |
| `User.AlreadySuspended` | Already suspended | Duplicate suspension | 409 | do not retry, check the operation |
| `User.NotSuspended` | Not suspended | Unsuspending an active account | 409 | do not retry, check the operation |
| `User.AlreadyDeleted` | Already deleted | Duplicate deletion | 409 | do not retry, check the operation |
| `User.NotDeleted` | Account is not deleted | Second stage of deletion (pseudonymization) on a live account — it removes the address and access of the account and must never run while the deletion is not final | 409 | do not retry, check the operation |
| `User.NotPending` | Not in the pending state | Action requires the pending state | 409 | do not retry, check the operation |
| `User.MfaAlreadyEnabled` | Second factor already active | Duplicate activation of the second factor | 409 | do not retry, check the operation |
| `User.MfaSetupNotStarted` | Second-factor setup not started | Confirmation without a started setup | 409 | do not retry, check the operation |
| `User.MfaNotEnabled` | Second factor not active | Action on the second factor although it is not active | 409 | do not retry, check the operation |
| `User.InvalidMfaCode` | Second-factor code invalid | Wrong code for an action on the account | 401 | check credentials |
| `OperatorUser.NotFound` | Operator account not found | Unknown ID of the operator account | 404 | do not retry, check the operation |
| `OperatorUser.EmailAlreadyExists` | Address of the operator account taken | Creation with an address that is already in use | 409 | do not retry, check the operation |
| `OperatorUser.CannotSuspendSelf` | Self-suspension not permitted | Operator account suspends itself | 403 | check permission or package |
| `OperatorUser.CannotModifySelf` | Own role cannot be changed | Operator account changes its own role | 403 | check permission or package |
| `OperatorUser.CannotSuspendOwner` | Owner cannot be suspended | Suspending the owner, transfer the owner role first | 409 | do not retry, check the operation |
| `OperatorUser.OwnerRoleImmutable` | Owner role cannot be changed | Role change on the owner, only the transfer replaces the owner | 409 | do not retry, check the operation |
| `OperatorUser.OwnerRequired` | Only the owner may do this | Roles, transfer, or creation by an account that is not the owner | 403 | check permission or package |
| `OperatorUser.OwnerTransferTargetInvalid` | Transfer target not possible | Own account, a suspended account, or the owner itself as the target | 422 | correct the input |
| `OperatorUser.OwnerTransferNotFound` | No transfer offer | Acceptance without an open offer to this account | 404 | do not retry, check the operation |
| `OperatorUser.OwnerTransferExpired` | Transfer offer expired | Acceptance after the seven days have passed | 409 | do not retry, check the operation |
| `OperatorUser.RecoveryCodeConsumed` | Recovery code used up | Reused code | 409 | do not retry, check the operation |
| `OperatorUser.AlreadySuspended` | Operator account already suspended | Duplicate suspension | 409 | do not retry, check the operation |
| `OperatorUser.NotSuspended` | Operator account not suspended | Unsuspending an active operator account | 409 | do not retry, check the operation |
| `ApiKey.NotFound` | API key not found | Unknown key ID | 404 | do not retry, check the operation |
| `ApiKey.ScopeEscalationBlocked` | Permission escalation blocked | Key with more permissions than its issuer | 403 | check permission or package |
| `ApiKey.ScopeNotKeyCapable` | Permission not intended for keys | A permission scope that includes a permission the catalog never assigns to keys. Separate from the escalation block: if you have too few permissions of your own, asking for more helps. If keys can never carry the permission, only a different approach helps | 422 | correct the input |
| `ApiKey.AlreadyRevoked` | API key already revoked | Duplicate revocation | 409 | do not retry, check the operation |
| `ApiKey.ExpiresAtInPast` | Expiry in the past | Issuing with an expiry in the past | 422 | correct the input |
| `OAuthClient.NotFound` | Connected application not found | A client ID for which no registration exists | 404 | do not retry, check the operation |
| `OAuthClient.AlreadyBlocked` | Application is already blocked | A second block on the same client. It would change nothing and only overwrite the first reason | 409 | do not retry, check the operation |
| `OAuthClient.NotBlocked` | Application is not blocked | Unblocking a client that is not blocked — usually the wrong ID | 409 | do not retry, check the operation |
| `OAuthAuthorization.NotFound` | Consent request not found | Opening or deciding with an unknown request ID | 404 | do not retry, check the operation |
| `OAuthAuthorization.AlreadyDecided` | Request already decided | A second allow or deny of the same request. Without this guard, a single approval would produce a second code | 409 | do not retry, check the operation |
| `OAuthAuthorization.Expired` | Consent request expired | The time limit has passed. Deliberately 410 and not 404: the request did exist, and the flow starts over from your application | 410 | do not retry, check the operation |
| `OAuthAuthorization.ScopeNotDelegatable` | Permission cannot be delegated to applications | The request names a permission key that the catalog never assigns to machines. Unlike having too few permissions of your own, asking does not help here, only a different approach | 422 | correct the input |
| `OAuthAuthorization.ScopeEscalationBlocked` | Permission escalation blocked | The consent asks for more than the consenting person holds | 422 | correct the input |
| `OAuthAuthorization.DelegationDisabled` | Delegated access switched off | This organization does not have the capability for delegated access. The request is stopped where the person decides, not only at the exchange | 403 | check permission or package |
| `OperatorApiKey.NotFound` | Operator key not found | Unknown key ID when rotating or revoking | 404 | do not retry, check the operation |
| `OperatorApiKey.PermissionEscalationBlocked` | Permission escalation blocked | Key with more permissions than its issuer holds | 403 | check permission or package |
| `OperatorApiKey.PermissionNotKeyCapable` | Permission not intended for keys | The requested permission is not on the allowlist for machine access | 422 | correct the input |
| `OperatorApiKey.AlreadyRevoked` | Operator key already revoked | Duplicate revocation — revocation is final (forensics) | 409 | do not retry, check the operation |
| `ScimToken.SsoProviderRequired` | No active company sign-in method | Issuing a SCIM token before the organization has an active sign-in method. The accounts created this way would otherwise have no sign-in procedure | 409 | do not retry, check the operation |
| `ScimToken.NotFound` | No SCIM token exists | Rotating or revoking although none has been issued | 404 | do not retry, check the operation |
| `ScimToken.AlreadyExists` | SCIM token already exists | A second issuance alongside a valid token. Switching goes through rotation and has a route of its own | 409 | do not retry, check the operation |
| `ScimToken.AlreadyRevoked` | SCIM token already revoked | Duplicate revocation — it is final | 409 | do not retry, check the operation |
| `Device.NotFound` | Device not found | Unknown device ID | 404 | do not retry, check the operation |
| `Device.DuplicateHardwareSerial` | Serial number duplicated | Reconnecting a web display under a known serial number with a different secret | 409 | do not retry, check the operation |
| `Device.ReregistrationPending` | Re-registration awaits confirmation | Registration of a paired device with a new key, for example after reflashing. The organization decides in the device record, and the rejection carries the device name in `details.deviceName`. For 24 hours after **Accept, keep displays**, the same key is issued a certificate | 409 | do not retry, check the operation |
| `Device.ReregistrationNotPending` | No re-registration open | Decision about a device that has not reported with a new key | 409 | do not retry, check the operation |
| `Device.CertFingerprintConflict` | Certificate fingerprint duplicated | Fingerprint already assigned | 409 | do not retry, check the operation |
| `Device.InvalidCsr` | Certificate request invalid | Malformed certificate request | 400 | correct the input |
| `Device.CertNotEligibleForRotation` | Rotation not permitted | Certificate cannot be rotated yet | 409 | do not retry, check the operation |
| `Device.AlreadyClaimed` | Device already claimed | Duplicate pairing, or a browser signs in under the ID of a paired web display. Its way back is **Create a new address** | 409 | do not retry, check the operation |
| `Device.NotActive` | Device not active | Action on an inactive device | 409 | do not retry, check the operation |
| `Device.Decommissioned` | Device decommissioned (legacy) | No longer issued. The device agent still reads the code as an order to restore factory settings | 409 | do not retry, check the operation |
| `Device.Blocked` | Device blocked | Re-registration, release, or a repeated block of a blocked device | 409 | do not retry, check the operation |
| `Device.NotBlocked` | Device not blocked | Unblocking a device that is not blocked | 409 | do not retry, check the operation |
| `Device.DisplaySecretInvalid` | Device secret unknown | Call from a web display with a wrong or missing secret | 401 | check credentials |
| `Device.ConnectLinkInvalid` | Connect link invalid | Link used up, expired, or display already taken over | 410 | do not retry, check the operation |

### Sign-in and sessions (Sessions)

Sign-in with a password, magic link, company sign-in, and platform-wide providers, second factor, refresh, password reset, and impersonation by the operator. The codes with 410 mark links that are used up or expired. A new link is the only way.

| Code | Meaning | Typical trigger | HTTP | Expected reaction |
|---|---|---|---|---|
| `Login.InvalidCredentials` | Sign-in credentials incorrect | Wrong password or wrong email address | 401 | check credentials |
| `Login.AccountSuspended` | Account suspended | Sign-in of a suspended account | 403 | check permission or package |
| `Login.TenantSuspended` | Organization suspended | Sign-in to a suspended organization | 403 | check permission or package |
| `Login.ChoiceTicketInvalid` | Choice ticket invalid | Organization choice with an unknown, expired, or already redeemed ticket (also: another device) | 401 | check credentials |
| `Login.OrganizationNotEligible` | Organization not selectable | The chosen organization is not in the ticket’s set | 403 | check permission or package |
| `Login.SsoRequired` | Company sign-in enforced | Password, magic link, or reset for an address in a verified domain of the company sign-in | 403 | check permission or package |
| `Login.HandoffTicketInvalid` | Handoff ticket invalid | Ticket unknown, expired (3 min), or already redeemed | 401 | check credentials |
| `Mfa.InvalidCode` | Second-factor code invalid | Wrong code at sign-in | 401 | check credentials |
| `Mfa.TooManyAttempts` | Too many second-factor attempts | Failed-attempt limit exceeded | 429 | wait (Retry-After) |
| `Mfa.NotEnabled` | Second factor not active | Sign-in with a second factor although none is active | 409 | do not retry, check the operation |
| `Session.NotFound` | Session not found | Unknown session ID | 404 | do not retry, check the operation |
| `Session.Revoked` | Session revoked | Use of a revoked session | 401 | check credentials |
| `Session.Expired` | Session expired | Expired session | 401 | check credentials |
| `RefreshToken.Invalid` | Refresh token invalid | Malformed or unknown token, or a token of the wrong session type on the route (organization ↔ operator account) | 401 | check credentials |
| `RefreshToken.TheftDetected` | Token theft detected | Reused refresh token | 401 | check credentials |
| `PasswordReset.TokenInvalid` | Reset token invalid | Malformed token | 400 | correct the input |
| `PasswordReset.TokenExpired` | Reset token expired | Expired token | 410 | do not retry, check the operation |
| `PasswordReset.TokenUsed` | Reset token already used | Already redeemed | 410 | do not retry, check the operation |
| `MagicLink.TokenInvalid` | Magic link invalid | Malformed token | 400 | correct the input |
| `MagicLink.TokenExpired` | Magic link expired | Expired token | 410 | do not retry, check the operation |
| `MagicLink.TokenUsed` | Magic link already used | Already redeemed | 410 | do not retry, check the operation |
| `Sso.StateInvalid` | Callback state invalid | Tampered or expired callback state | 401 | check credentials |
| `Sso.ProviderUnavailable` | Sign-in method unavailable | Starting sign-in with an unknown, inactive, or unreachable provider | 404 | do not retry, check the operation |
| `Sso.CallbackFailed` | Callback failed | The provider reports an error, or the token exchange or the check of the ID token fails | 401 | check credentials |
| `Social.ProviderUnavailable` | Provider not set up | Starting sign-in with Google, Microsoft, or Apple although the platform has not configured the provider | 503 | retry later, report the trace ID if it recurs |
| `Social.EmailUnverified` | Address not verified | The provider returns no verified address — without it, no first link is created | 403 | check permission or package |
| `Social.LinkConflict` | ID already taken | The same provider ID is already attached to another account | 409 | do not retry, check the operation |
| `Social.NoAccount` | No account for the address | The verified address belongs to no account — the path ends in sign-up | 404 | do not retry, check the operation |
| `Impersonation.ReasonRequired` | Reason required | Impersonation without a reason | 422 | correct the input |
| `Impersonation.LifetimeExceeded` | Impersonation expired | Upper limit of 4 hours exceeded | 401 | check credentials |

## Count

This page lists **103 codes**. Together with the other six error-code pages this gives 493 domain codes (4xx) and 119 server errors (5xx), 612 codes in all — the complete catalog of the platform.

## Related

- [Authentication: keys and sessions](/api/authentication)
- [The error format](/api/error-format)
