better_auth/
error.rs

1use thiserror::Error;
2
3/// Authentication framework error types
4#[derive(Error, Debug)]
5pub enum AuthError {
6    #[error("Configuration error: {0}")]
7    Config(String),
8    
9    #[error("Database error: {0}")]
10    Database(#[from] DatabaseError),
11    
12    #[error("Serialization error: {0}")]
13    Serialization(#[from] serde_json::Error),
14    
15    #[error("Invalid credentials")]
16    InvalidCredentials,
17    
18    #[error("User not found")]
19    UserNotFound,
20    
21    #[error("Session not found or expired")]
22    SessionNotFound,
23    
24    #[error("Plugin error: {plugin} - {message}")]
25    Plugin { plugin: String, message: String },
26    
27    #[error("Invalid request: {0}")]
28    InvalidRequest(String),
29    
30    #[error("Internal server error: {0}")]
31    Internal(String),
32    
33    #[error("Authentication required")]
34    Unauthenticated,
35    
36    #[error("Insufficient permissions")]
37    Unauthorized,
38    
39    #[error("Password hashing error: {0}")]
40    PasswordHash(String),
41    
42    #[error("JWT error: {0}")]
43    Jwt(#[from] jsonwebtoken::errors::Error),
44}
45
46#[derive(Error, Debug)]
47pub enum DatabaseError {
48    #[error("Connection error: {0}")]
49    Connection(String),
50    
51    #[error("Query error: {0}")]
52    Query(String),
53    
54    #[error("Migration error: {0}")]
55    Migration(String),
56    
57    #[error("Constraint violation: {0}")]
58    Constraint(String),
59    
60    #[error("Transaction error: {0}")]
61    Transaction(String),
62}
63
64#[cfg(feature = "sqlx-postgres")]
65impl From<sqlx::Error> for DatabaseError {
66    fn from(err: sqlx::Error) -> Self {
67        match err {
68            sqlx::Error::Database(db_err) => {
69                if db_err.is_unique_violation() {
70                    DatabaseError::Constraint(db_err.to_string())
71                } else {
72                    DatabaseError::Query(db_err.to_string())
73                }
74            }
75            sqlx::Error::PoolClosed => DatabaseError::Connection("Pool closed".to_string()),
76            sqlx::Error::PoolTimedOut => DatabaseError::Connection("Pool timed out".to_string()),
77            _ => DatabaseError::Query(err.to_string()),
78        }
79    }
80}
81
82#[cfg(feature = "sqlx-postgres")]
83impl From<sqlx::Error> for AuthError {
84    fn from(err: sqlx::Error) -> Self {
85        AuthError::Database(DatabaseError::from(err))
86    }
87}
88
89pub type AuthResult<T> = Result<T, AuthError>;
90
91impl AuthError {
92    pub fn plugin(plugin: &str, message: impl Into<String>) -> Self {
93        Self::Plugin {
94            plugin: plugin.to_string(),
95            message: message.into(),
96        }
97    }
98    
99    pub fn config(message: impl Into<String>) -> Self {
100        Self::Config(message.into())
101    }
102    
103    pub fn internal(message: impl Into<String>) -> Self {
104        Self::Internal(message.into())
105    }
106}