Errors Error types, HTTP status codes, and error response format.
All errors return JSON:
{
"message" : "Description of the error"
}
For 5xx errors, the actual error details are hidden and a generic message is returned to avoid leaking internal information.
Variant HTTP Status Description BadRequest400 Malformed request InvalidRequest400 Invalid request parameters Validation400 Input validation failed InvalidCredentials401 Wrong email/password Unauthenticated401 No valid session token SessionNotFound401 Session token not found or expired Forbidden403 Action not allowed Unauthorized403 Insufficient permissions UserNotFound404 User does not exist NotFound404 Resource not found Conflict409 Duplicate resource (email, username) RateLimited429 Too many requests NotImplemented501 Feature not implemented Config500 Configuration error Database500 Database operation failed Serialization500 JSON serialization error Plugin500 Plugin-specific error Internal500 Unexpected internal error PasswordHash500 Password hashing failure Jwt500 JWT encoding/decoding error
Database errors are wrapped in AuthError::Database:
Variant Description ConnectionFailed to connect to database QueryQuery execution failed MigrationMigration failed ConstraintUnique constraint violation TransactionTransaction failed
use better_auth :: error :: { AuthError , AuthResult };
fn handle_result (result : AuthResult <()>) {
match result {
Ok (()) => println! ( "Success" ),
Err (e) => {
println! ( "Status: {}" , e . status_code ());
println! ( "Message: {}" , e . message ());
}
}
}
Constructors for common errors:
AuthError :: bad_request ( "Invalid input" );
AuthError :: forbidden ( "Not allowed" );
AuthError :: not_found ( "User not found" );
AuthError :: conflict ( "Email already exists" );
AuthError :: internal ( "Unexpected error" );
AuthError :: validation ( "Password too short" );
AuthError :: plugin ( "my-plugin" , "Something went wrong" );
AuthError :: not_implemented ( "Feature not available yet" );
Error When Resolution UnauthenticatedMissing or invalid session token Include a valid Authorization: Bearer <token> header or session cookie InvalidCredentialsWrong email/password combination Check credentials and retry SessionNotFoundExpired or revoked session Re-authenticate to get a new session
Error When Resolution ForbiddenUser lacks required role (e.g., admin) Ensure the user has the appropriate role UnauthorizedInsufficient RBAC permissions Check organization role and permissions
Error When Resolution ValidationRequest body fails validation Check required fields, formats, and constraints BadRequestMalformed or missing request data Ensure the request matches the expected format
Error When Resolution UserNotFoundReferenced user doesn't exist Verify the user ID NotFoundResource (org, member, key, etc.) not found Check the resource ID and ownership ConflictEmail, username, or slug already exists Use a different value
Error When Resolution RateLimitedToo many requests in the time window Wait for retryAfter seconds before retrying
Error When BadRequest("Unknown provider")Provider name not registered BadRequest("Missing code parameter")OAuth callback missing authorization code BadRequest("Provider mismatch")State provider doesn't match callback provider Conflict("Social account already linked")Provider account linked to another user
Error When NotFound("Two-factor authentication not enabled")2FA not set up for user BadRequest("Invalid backup code")Backup code doesn't match BadRequest("No backup codes available")All backup codes used
Error When Forbidden("Insufficient permissions")Role lacks required RBAC permission Conflict("Slug already taken")Organization slug already in use
Error When NotImplemented(...)allow_insecure_unverified_assertion is falseBadRequest("Invalid or expired ... challenge")Challenge expired or already used
When using the Axum integration, AuthError is automatically converted to an HTTP response:
use axum :: { Json , response :: IntoResponse };
use better_auth :: error :: AuthError ;
async fn my_handler () -> Result < impl IntoResponse , AuthError > {
// AuthError automatically becomes the right HTTP status + JSON body
Err ( AuthError :: bad_request ( "Something went wrong" ))
}