Skip to content

Error codes

Auth-related HTTP errors use Litestar ClientException (or guard failures) with a machine-readable code in extra where the library controls the response. Clients should rely on code, not only on detail text.

Typical response shape (conceptual):

{
  "status_code": 400,
  "detail": "Human-readable message",
  "extra": { "code": "LOGIN_BAD_CREDENTIALS" }
}

Exact JSON layout follows your Litestar exception handler configuration.

ErrorCode reference

Code Typical HTTP Meaning
UNKNOWN varies Generic fallback: base LitestarAuthError default, or plugin JSON code when extra omits a string code.
AUTHENTICATION_FAILED 401 Generic authentication failure (guards / middleware).
TOKEN_PROCESSING_FAILED 401 / 400 / 503 Invalid or unusable token in ordinary validation paths (401 / 400); 503 when a bundled route cannot persist a required JWT revocation or TOTP pending-login JTI because the denylist is at capacity (fail-closed; see Security and Guides — Security).
CONFIGURATION_INVALID 500 / startup Misconfiguration.
USER_NOT_FOUND 404 User id does not exist.
USER_ALREADY_EXISTS 400 Duplicate user in a non-endpoint-specific default exception context.
REGISTER_FAILED 400 Generic registration failure.
LOGIN_BAD_CREDENTIALS 400 Wrong password or unknown user (login).
LOGIN_ACCOUNT_UNAVAILABLE 400 Account-state policy blocked sign-in, refresh, OAuth local session issue, or another account-state gated flow.
AUTHORIZATION_DENIED 403 Guard denied access.
INSUFFICIENT_ROLES 403 Role-based guard denial. Structured role context stays on the exception object but is omitted from default HTTP responses.
ROLE_ALREADY_EXISTS 409 Opt-in contrib role-admin create conflict.
ROLE_NOT_FOUND 404 Opt-in contrib role-admin requested role missing.
ROLE_STILL_ASSIGNED 409 Opt-in contrib role-admin delete refused while users still hold the role.
ROLE_ASSIGNMENT_USER_NOT_FOUND 404 Opt-in contrib role-admin assignment target user missing.
ROLE_NAME_INVALID 422 Opt-in contrib role-admin role name invalid or immutable-name patch attempted.
RESET_PASSWORD_BAD_TOKEN 400 Reset token invalid/expired.
RESET_PASSWORD_INVALID_PASSWORD 400 New password rejected.
VERIFY_USER_BAD_TOKEN 400 Verification token invalid.
VERIFY_USER_ALREADY_VERIFIED 400 Already verified.
UPDATE_USER_EMAIL_ALREADY_EXISTS 400 Email collision on update.
UPDATE_USER_INVALID_PASSWORD 400 Current password wrong / policy.
SUPERUSER_CANNOT_DELETE_SELF 403 Self-delete forbidden.
OAUTH_NOT_AVAILABLE_EMAIL 400 Provider did not supply email.
OAUTH_STATE_INVALID 400 OAuth state cookie missing/invalid.
OAUTH_EMAIL_NOT_VERIFIED 400 Associate-by-email requires verified provider email.
OAUTH_USER_ALREADY_EXISTS 400 OAuth would create duplicate against policy.
OAUTH_ACCOUNT_ALREADY_LINKED 400 Provider identity bound to another user.
REQUEST_BODY_INVALID 400 / 422 Body failed validation or request decoding rejected undeclared fields.
LOGIN_PAYLOAD_INVALID 422 Login body shape invalid.
REFRESH_TOKEN_INVALID 401 Refresh rejected.
TOTP_PENDING_BAD_TOKEN 400 Pending login token invalid.
TOTP_CODE_INVALID 400 Wrong or reused TOTP code.
TOTP_ALREADY_ENABLED 400 TOTP already active.
TOTP_ENROLL_BAD_TOKEN 400 Enrollment token invalid.
TOTP_STEPUP_REQUIRED 403 A protected operation requires a recent TOTP verification marker or a valid inline TOTP code. Prompt the user for TOTP and retry the operation from the same session; see TOTP step-up for sensitive operations.
API_KEY_INVALID 401 / 404 API-key credential is absent, malformed, unknown, foreign to the current user, or failed non-enumerating lookup. Self-service metadata routes use 404 for missing or foreign key ids.
API_KEY_REVOKED 401 Parsed API-key credential belongs to a revoked key.
API_KEY_EXPIRED 401 Parsed API-key credential belongs to an expired key.
API_KEY_SCOPE_DENIED 400 / 403 Requested key scopes are outside allowed_scopes, or an API-key route guard denied the current request because required scopes or role-downscoped access were missing.
API_KEY_LIMIT_REACHED 400 User has reached ApiKeyConfig.max_keys_per_user active keys.
API_KEY_SIGNATURE_INVALID 401 Signed API-key request is malformed, uses the wrong key mode, has a bad signature, lacks signing secret material, or cannot use the configured nonce store.
API_KEY_SIGNATURE_TIMESTAMP_SKEW 401 Signed API-key request X-Auth-Date is outside the configured skew window.
API_KEY_SIGNATURE_NONCE_REPLAY 401 Signed API-key request reused a nonce within the nonce-store TTL.

USER_ALREADY_EXISTS, REGISTER_FAILED, and UPDATE_USER_INVALID_PASSWORD keep stable HTTP mappings even though the corresponding Python exceptions now use keyword-only structured context.

Source of truth in code: litestar_auth._error_codes.ErrorCode (re-exported from litestar_auth.exceptions) and controller ClientException sites. Full exception hierarchy: Python API — Exceptions.

LOGIN_ACCOUNT_UNAVAILABLE intentionally uses one opaque 400 response for inactive and unverified account-state failures so external observers cannot enumerate account state after valid credentials. Operators can correlate the internal inactive / unverified reason through the account_state_failure structured log event emitted on the litestar_auth.security logger.

Enumeration safety

POST .../register is intentionally enumeration-resistant for domain failures: duplicate identifiers, password-policy failures, and manager authorization rejections all use the same 400 / REGISTER_FAILED response. POST .../forgot-password is also enumeration-resistant: successful response does not reveal whether the email exists. See Registration guide.