Skip to main content

better_auth_diesel_sqlite/
error.rs

1//! Error types and conversion to `better-auth-core`'s `AuthError`.
2
3use better_auth_core::error::{AuthError, DatabaseError};
4
5/// Errors specific to the `Diesel` `SQLite` adapter.
6#[derive(Debug, thiserror::Error)]
7pub enum AdapterError {
8    /// Database query or connection error from `Diesel`.
9    #[error("database error: {0}")]
10    Database(#[from] diesel::result::Error),
11
12    /// Connection pool error.
13    #[error("pool error: {0}")]
14    Pool(String),
15
16    /// Migration execution error.
17    #[error("migration error: {0}")]
18    Migration(String),
19
20    /// Data conversion error (e.g., invalid UUID, timestamp, JSON).
21    #[error("conversion error: {0}")]
22    Conversion(String),
23
24    /// Connection setup error (pragmas, initialization).
25    #[error("connection error: {0}")]
26    Connection(String),
27}
28
29impl From<AdapterError> for AuthError {
30    fn from(err: AdapterError) -> Self {
31        match err {
32            AdapterError::Database(diesel_err) => {
33                AuthError::Database(diesel_to_database_error(diesel_err))
34            }
35            AdapterError::Pool(msg) => AuthError::Database(DatabaseError::Connection(msg)),
36            AdapterError::Migration(msg) => AuthError::Database(DatabaseError::Migration(msg)),
37            AdapterError::Conversion(msg) => AuthError::Database(DatabaseError::Query(msg)),
38            AdapterError::Connection(msg) => AuthError::Database(DatabaseError::Connection(msg)),
39        }
40    }
41}
42
43/// Convert a `Diesel` error into a `better-auth-core` `DatabaseError`.
44///
45/// This is a free function rather than a `From` impl because both types
46/// are defined in external crates (orphan rule).
47pub(crate) fn diesel_to_database_error(err: diesel::result::Error) -> DatabaseError {
48    match err {
49        diesel::result::Error::NotFound => DatabaseError::Query("Record not found".to_string()),
50        diesel::result::Error::DatabaseError(
51            diesel::result::DatabaseErrorKind::UniqueViolation,
52            info,
53        ) => DatabaseError::Constraint(info.message().to_string()),
54        diesel::result::Error::DatabaseError(
55            diesel::result::DatabaseErrorKind::ForeignKeyViolation,
56            info,
57        ) => DatabaseError::Constraint(info.message().to_string()),
58        diesel::result::Error::DatabaseError(_, info) => {
59            DatabaseError::Query(info.message().to_string())
60        }
61        diesel::result::Error::RollbackTransaction => {
62            DatabaseError::Transaction("Transaction rolled back".to_string())
63        }
64        other => DatabaseError::Query(other.to_string()),
65    }
66}
67
68/// Helper to convert a `Diesel` error directly into an `AuthError`.
69pub(crate) fn diesel_to_auth_error(err: diesel::result::Error) -> AuthError {
70    AuthError::Database(diesel_to_database_error(err))
71}