Errors
This page helps you handle the errors the Admin API and the Account API answer.
Every error comes back as a JSON body with the same two fields:
{ "error_code": "VALIDATION_ERROR", "error_description": "SMTP host is required."}Decide what to do from the HTTP status first: a 4xx is something your request can fix, and a 5xx is a problem on the server. Then read error_code for the specific case, and show or log error_description.
The fields
Section titled “The fields”error_codeis a stable identifier for the failure. It’s either anUPPER_SNAKEcode from the table below, or, for a refused field the auth server can describe in several languages, a catalog key in dotted lowercase, such asvalidator.email.invalid_format.error_descriptionis a sentence for people. For a catalog key it’s in the request’s language; otherwise it’s in English. Don’t match on it: the wording can change, the code won’t.
The protocol endpoints, /auth/authorize, /auth/token, /connect/register and /userinfo, answer errors in the format their standards define, not this one. Authorize, Token and UserInfo cover theirs, and Dynamic client registration the registration endpoint’s.
Error codes
Section titled “Error codes”This is every UPPER_SNAKE code the two APIs answer.
| Code | Status | Meaning |
|---|---|---|
VALIDATION_ERROR |
400 |
A value was refused. error_description says which and why. |
INVALID_REQUEST_BODY |
400 |
The body isn’t the JSON the operation expects. |
INVALID_REQUEST |
400 |
The Authorization header or the access_token parameter was sent twice, the token was sent two ways at once, or a form body doesn’t parse. |
EMAIL_TOO_LONG |
400 |
The new user’s email address is longer than 60 characters. |
VALUE_TOO_LONG |
400 |
A user attribute’s value is longer than 250 characters. |
FILE_TOO_LARGE |
400 |
The uploaded picture or logo is over the size limit, or the form doesn’t parse. |
NO_FILE |
400 |
The upload has no picture field. |
AUTHENTICATION_FAILED |
400 |
The password sent to confirm a password change, an email change, or turning two-factor authentication on or off is wrong. For two-factor authentication, a missing password answers it too. |
OTP_CODE_REQUIRED |
400 |
Two-factor authentication was turned on without a code. |
INVALID_OTP_CODE |
400 |
The code isn’t six digits, or it doesn’t match the authenticator. |
OTP_ENROLLMENT_NOT_PENDING |
400 |
No enrollment is pending, or it expired. Start a new one with GET /api/v1/account/otp/enrollment. |
SECRET_KEY_NOT_ACCEPTED |
400 |
The request sent a secretKey. Start an enrollment and send only the code from the authenticator. |
OTP_ALREADY_ENABLED |
400 |
Two-factor authentication is already on. |
OTP_NOT_ENABLED |
400 |
Two-factor authentication is already off. |
INVALID_OR_EXPIRED_VERIFICATION_CODE |
400 |
The email verification code is wrong or has expired. |
SMTP_NOT_ENABLED |
400 |
The operation needs to send email, and SMTP is off: a test email, or sending or checking an email verification code. |
SEND_FAILED |
400 |
The test email couldn’t be sent. error_description says what to check. |
ACCESS_TOKEN_REQUIRED |
401 |
No access token was sent. |
INVALID_TOKEN |
401 |
The token is malformed, expired, not an access token for authserver, or its user or session is gone. |
INVALID_SESSION |
401 |
On POST /api/v1/account/logout-request: the token carries no session id (sid), its session is gone, or the token’s client isn’t part of that session. |
INSUFFICIENT_SCOPE |
403 |
The token carries none of the scopes the operation accepts. The WWW-Authenticate header says error="insufficient_scope". |
USER_CONTEXT_REQUIRED |
403 |
An Account API call was made with a token that wasn’t issued for a user, such as one from the client credentials flow, carrying authserver:manage-account. Without it, the answer is INSUFFICIENT_SCOPE. |
FORBIDDEN |
403 |
The token is valid, but the consent or session it names belongs to another user. |
MANAGE_SCOPE_REQUIRED |
403 |
The request acts on an administrator or an administrative permission, which only authserver:manage may do. See Administrators. |
NOT_FOUND |
404 |
Nothing has that id. |
CONCURRENT_UPDATE |
409 |
Another request changed what yours was based on. Nothing was saved: read it again and retry. |
EMAIL_ALREADY_EXISTS |
409 |
Another user already has that email address. |
LAST_ADMINISTRATOR |
409 |
The change would leave no enabled user holding authserver:manage. Grant it to another user first. |
ROTATION_IN_PROGRESS |
409 |
Another signing key rotation won the race, and this call rotated nothing. Don’t retry: the rotation it ran into already happened. |
TOO_MANY_REQUESTS |
429 |
A rate limit was reached. The Retry-After header says how many seconds to wait. |
INTERNAL_SERVER_ERROR |
500 |
The request failed inside the server. error_description ends with a request id an operator can find in the server’s log. Retrying is reasonable. |
KEY_SET_INCOMPLETE |
500 |
A signing key rotation found no current or no next key. That’s a deployment problem a retry won’t clear. error_description ends with a request id, as for INTERNAL_SERVER_ERROR. |
Saving a whole list
Section titled “Saving a whole list”An operation that replaces a whole list, such as a client’s redirect URIs or a user’s groups, also takes the list as you last read it, in a field named expected and the list’s name, such as expectedRedirectURIs. When the stored list is no longer that one, because someone else saved it in between, the save is answered 409 with CONCURRENT_UPDATE and changes nothing. Read the list again, apply your change to it, and save again.