atagen

macltok

public
Star0
Watch0
31ce2453c82f470aa8b5d3861ab0eec4273afc5d
3
ssh://brewery@pls.lobotomise.me:33/atagen/macltok.git

Blame: src/error.rs

31ce2453c82fatagen2026-09-24 13:07 UTC1
use std::sync::Arc;
96fdf90aacd6atagen2026-09-08 08:24 UTC2
96fdf90aacd6atagen2026-09-08 08:24 UTC3
use matrix_sdk::{
96fdf90aacd6atagen2026-09-08 08:24 UTC4
    HttpError, RefreshTokenError,
96fdf90aacd6atagen2026-09-08 08:24 UTC5
    authentication::oauth::error::{
96fdf90aacd6atagen2026-09-08 08:24 UTC6
        OAuthAuthorizationCodeError, OAuthDiscoveryError, OAuthError, OAuthTokenRevocationError,
96fdf90aacd6atagen2026-09-08 08:24 UTC7
        RequestTokenError,
96fdf90aacd6atagen2026-09-08 08:24 UTC8
    },
96fdf90aacd6atagen2026-09-08 08:24 UTC9
    encryption::{
96fdf90aacd6atagen2026-09-08 08:24 UTC10
        identities::{ManualVerifyError, RequestVerificationError},
96fdf90aacd6atagen2026-09-08 08:24 UTC11
        recovery::RecoveryError,
96fdf90aacd6atagen2026-09-08 08:24 UTC12
        secret_storage::{ImportError, SecretStorageError},
96fdf90aacd6atagen2026-09-08 08:24 UTC13
    },
96fdf90aacd6atagen2026-09-08 08:24 UTC14
};
31ce2453c82fatagen2026-09-24 13:07 UTC15
#[cfg(feature = "serde")]
31ce2453c82fatagen2026-09-24 13:07 UTC16
use serde::{Deserialize, Serialize};
96fdf90aacd6atagen2026-09-08 08:24 UTC17
31ce2453c82fatagen2026-09-24 13:07 UTC18
use crate::InteractiveAuthChallenge;
96fdf90aacd6atagen2026-09-08 08:24 UTC19
31ce2453c82fatagen2026-09-24 13:07 UTC20
/// the one thing that goes wrong, for commands and queries alike. match on `kind`, show `message`
31ce2453c82fatagen2026-09-24 13:07 UTC21
#[derive(Clone, Debug, thiserror::Error)]
31ce2453c82fatagen2026-09-24 13:07 UTC22
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
96fdf90aacd6atagen2026-09-08 08:24 UTC23
#[error("{message}")]
31ce2453c82fatagen2026-09-24 13:07 UTC24
#[non_exhaustive]
31ce2453c82fatagen2026-09-24 13:07 UTC25
pub struct Error {
31ce2453c82fatagen2026-09-24 13:07 UTC26
    pub kind: ErrorKind,
31ce2453c82fatagen2026-09-24 13:07 UTC27
    pub message: String,
31ce2453c82fatagen2026-09-24 13:07 UTC28
    /// set when the server wants interactive auth before it'll do the thing
31ce2453c82fatagen2026-09-24 13:07 UTC29
    pub challenge: Option<Box<InteractiveAuthChallenge>>,
96fdf90aacd6atagen2026-09-08 08:24 UTC30
    #[source]
31ce2453c82fatagen2026-09-24 13:07 UTC31
    #[cfg_attr(feature = "serde", serde(skip))]
31ce2453c82fatagen2026-09-24 13:07 UTC32
    source: Option<Arc<dyn std::error::Error + Send + Sync>>,
96fdf90aacd6atagen2026-09-08 08:24 UTC33
}
96fdf90aacd6atagen2026-09-08 08:24 UTC34
31ce2453c82fatagen2026-09-24 13:07 UTC35
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
31ce2453c82fatagen2026-09-24 13:07 UTC36
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
31ce2453c82fatagen2026-09-24 13:07 UTC37
#[non_exhaustive]
31ce2453c82fatagen2026-09-24 13:07 UTC38
pub enum ErrorKind {
31ce2453c82fatagen2026-09-24 13:07 UTC39
    /// the engine stopped, or the task doing the work died, before answering
31ce2453c82fatagen2026-09-24 13:07 UTC40
    Interrupted,
31ce2453c82fatagen2026-09-24 13:07 UTC41
    Unauthenticated,
31ce2453c82fatagen2026-09-24 13:07 UTC42
    InteractiveAuthRequired,
31ce2453c82fatagen2026-09-24 13:07 UTC43
    Invalid,
31ce2453c82fatagen2026-09-24 13:07 UTC44
    RoomUnknown,
31ce2453c82fatagen2026-09-24 13:07 UTC45
    RoomNotOpen,
31ce2453c82fatagen2026-09-24 13:07 UTC46
    TimelineNotOpen,
31ce2453c82fatagen2026-09-24 13:07 UTC47
    RoomBusy,
31ce2453c82fatagen2026-09-24 13:07 UTC48
    QueueFull,
31ce2453c82fatagen2026-09-24 13:07 UTC49
    EmptyBody,
31ce2453c82fatagen2026-09-24 13:07 UTC50
    MediaUnknown,
31ce2453c82fatagen2026-09-24 13:07 UTC51
    MediaTooLarge,
31ce2453c82fatagen2026-09-24 13:07 UTC52
    MediaUnavailable,
31ce2453c82fatagen2026-09-24 13:07 UTC53
    VerificationInactive,
31ce2453c82fatagen2026-09-24 13:07 UTC54
    VerificationUnsupported,
31ce2453c82fatagen2026-09-24 13:07 UTC55
    NoCrossSigningIdentity,
31ce2453c82fatagen2026-09-24 13:07 UTC56
    RecoveryRejected,
31ce2453c82fatagen2026-09-24 13:07 UTC57
    Network,
31ce2453c82fatagen2026-09-24 13:07 UTC58
    Server,
31ce2453c82fatagen2026-09-24 13:07 UTC59
    Store,
31ce2453c82fatagen2026-09-24 13:07 UTC60
    Timeline,
31ce2453c82fatagen2026-09-24 13:07 UTC61
    Encryption,
31ce2453c82fatagen2026-09-24 13:07 UTC62
    Other,
31ce2453c82fatagen2026-09-24 13:07 UTC63
}
31ce2453c82fatagen2026-09-24 13:07 UTC64
31ce2453c82fatagen2026-09-24 13:07 UTC65
impl Error {
31ce2453c82fatagen2026-09-24 13:07 UTC66
    pub(crate) fn new(kind: ErrorKind, message: impl Into<String>) -> Self {
96fdf90aacd6atagen2026-09-08 08:24 UTC67
        Self {
96fdf90aacd6atagen2026-09-08 08:24 UTC68
            kind,
96fdf90aacd6atagen2026-09-08 08:24 UTC69
            message: message.into(),
31ce2453c82fatagen2026-09-24 13:07 UTC70
            challenge: None,
96fdf90aacd6atagen2026-09-08 08:24 UTC71
            source: None,
96fdf90aacd6atagen2026-09-08 08:24 UTC72
        }
96fdf90aacd6atagen2026-09-08 08:24 UTC73
    }
96fdf90aacd6atagen2026-09-08 08:24 UTC74
96fdf90aacd6atagen2026-09-08 08:24 UTC75
    pub(crate) fn with_source(
31ce2453c82fatagen2026-09-24 13:07 UTC76
        kind: ErrorKind,
96fdf90aacd6atagen2026-09-08 08:24 UTC77
        message: impl Into<String>,
96fdf90aacd6atagen2026-09-08 08:24 UTC78
        source: impl std::error::Error + Send + Sync + 'static,
96fdf90aacd6atagen2026-09-08 08:24 UTC79
    ) -> Self {
96fdf90aacd6atagen2026-09-08 08:24 UTC80
        Self {
31ce2453c82fatagen2026-09-24 13:07 UTC81
            source: Some(Arc::new(source)),
31ce2453c82fatagen2026-09-24 13:07 UTC82
            ..Self::new(kind, message)
31ce2453c82fatagen2026-09-24 13:07 UTC83
        }
31ce2453c82fatagen2026-09-24 13:07 UTC84
    }
31ce2453c82fatagen2026-09-24 13:07 UTC85
31ce2453c82fatagen2026-09-24 13:07 UTC86
    pub(crate) fn interrupted() -> Self {
31ce2453c82fatagen2026-09-24 13:07 UTC87
        Self::new(
31ce2453c82fatagen2026-09-24 13:07 UTC88
            ErrorKind::Interrupted,
31ce2453c82fatagen2026-09-24 13:07 UTC89
            "the engine stopped before the operation finished",
31ce2453c82fatagen2026-09-24 13:07 UTC90
        )
31ce2453c82fatagen2026-09-24 13:07 UTC91
    }
31ce2453c82fatagen2026-09-24 13:07 UTC92
31ce2453c82fatagen2026-09-24 13:07 UTC93
    pub(crate) fn room_unknown() -> Self {
31ce2453c82fatagen2026-09-24 13:07 UTC94
        Self::new(
31ce2453c82fatagen2026-09-24 13:07 UTC95
            ErrorKind::RoomUnknown,
31ce2453c82fatagen2026-09-24 13:07 UTC96
            "room is not available in the local store",
31ce2453c82fatagen2026-09-24 13:07 UTC97
        )
31ce2453c82fatagen2026-09-24 13:07 UTC98
    }
31ce2453c82fatagen2026-09-24 13:07 UTC99
31ce2453c82fatagen2026-09-24 13:07 UTC100
    pub(crate) fn interactive_auth(challenge: InteractiveAuthChallenge) -> Self {
31ce2453c82fatagen2026-09-24 13:07 UTC101
        Self {
31ce2453c82fatagen2026-09-24 13:07 UTC102
            challenge: Some(Box::new(challenge)),
31ce2453c82fatagen2026-09-24 13:07 UTC103
            ..Self::new(
31ce2453c82fatagen2026-09-24 13:07 UTC104
                ErrorKind::InteractiveAuthRequired,
31ce2453c82fatagen2026-09-24 13:07 UTC105
                "interactive authentication is required",
31ce2453c82fatagen2026-09-24 13:07 UTC106
            )
96fdf90aacd6atagen2026-09-08 08:24 UTC107
        }
96fdf90aacd6atagen2026-09-08 08:24 UTC108
    }
96fdf90aacd6atagen2026-09-08 08:24 UTC109
96fdf90aacd6atagen2026-09-08 08:24 UTC110
    pub(crate) fn from_sdk(message: impl Into<String>, source: matrix_sdk::Error) -> Self {
96fdf90aacd6atagen2026-09-08 08:24 UTC111
        Self::with_source(classify_sdk_error(&source), message, source)
96fdf90aacd6atagen2026-09-08 08:24 UTC112
    }
96fdf90aacd6atagen2026-09-08 08:24 UTC113
96fdf90aacd6atagen2026-09-08 08:24 UTC114
    pub(crate) fn from_http(message: impl Into<String>, source: HttpError) -> Self {
96fdf90aacd6atagen2026-09-08 08:24 UTC115
        Self::with_source(classify_http_error(&source), message, source)
96fdf90aacd6atagen2026-09-08 08:24 UTC116
    }
31ce2453c82fatagen2026-09-24 13:07 UTC117
96fdf90aacd6atagen2026-09-08 08:24 UTC118
    pub(crate) fn from_refresh_token(
96fdf90aacd6atagen2026-09-08 08:24 UTC119
        message: impl Into<String>,
96fdf90aacd6atagen2026-09-08 08:24 UTC120
        source: RefreshTokenError,
96fdf90aacd6atagen2026-09-08 08:24 UTC121
    ) -> Self {
96fdf90aacd6atagen2026-09-08 08:24 UTC122
        Self::with_source(classify_refresh_token_error(&source), message, source)
96fdf90aacd6atagen2026-09-08 08:24 UTC123
    }
96fdf90aacd6atagen2026-09-08 08:24 UTC124
96fdf90aacd6atagen2026-09-08 08:24 UTC125
    pub(crate) fn from_recovery(message: impl Into<String>, source: RecoveryError) -> Self {
96fdf90aacd6atagen2026-09-08 08:24 UTC126
        let kind = match &source {
96fdf90aacd6atagen2026-09-08 08:24 UTC127
            RecoveryError::Sdk(source) => classify_sdk_error(source),
96fdf90aacd6atagen2026-09-08 08:24 UTC128
            RecoveryError::SecretStorage(SecretStorageError::Sdk(source)) => {
96fdf90aacd6atagen2026-09-08 08:24 UTC129
                classify_sdk_error(source)
96fdf90aacd6atagen2026-09-08 08:24 UTC130
            }
96fdf90aacd6atagen2026-09-08 08:24 UTC131
            RecoveryError::SecretStorage(SecretStorageError::ImportError { error, .. }) => {
96fdf90aacd6atagen2026-09-08 08:24 UTC132
                match error {
96fdf90aacd6atagen2026-09-08 08:24 UTC133
                    ImportError::Sdk(source) => classify_sdk_error(source),
31ce2453c82fatagen2026-09-24 13:07 UTC134
                    _ => ErrorKind::RecoveryRejected,
96fdf90aacd6atagen2026-09-08 08:24 UTC135
                }
96fdf90aacd6atagen2026-09-08 08:24 UTC136
            }
96fdf90aacd6atagen2026-09-08 08:24 UTC137
            RecoveryError::SecretStorage(SecretStorageError::Verification(source)) => {
96fdf90aacd6atagen2026-09-08 08:24 UTC138
                match source {
96fdf90aacd6atagen2026-09-08 08:24 UTC139
                    ManualVerifyError::Http(source) => classify_http_error(source),
31ce2453c82fatagen2026-09-24 13:07 UTC140
                    _ => ErrorKind::RecoveryRejected,
96fdf90aacd6atagen2026-09-08 08:24 UTC141
                }
96fdf90aacd6atagen2026-09-08 08:24 UTC142
            }
96fdf90aacd6atagen2026-09-08 08:24 UTC143
            RecoveryError::SecretStorage(SecretStorageError::SecretStorageKey(_)) => {
31ce2453c82fatagen2026-09-24 13:07 UTC144
                ErrorKind::RecoveryRejected
96fdf90aacd6atagen2026-09-08 08:24 UTC145
            }
31ce2453c82fatagen2026-09-24 13:07 UTC146
            RecoveryError::SecretStorage(SecretStorageError::Storage(_)) => ErrorKind::Store,
96fdf90aacd6atagen2026-09-08 08:24 UTC147
            RecoveryError::BackupExistsOnServer | RecoveryError::SecretStorage(_) => {
31ce2453c82fatagen2026-09-24 13:07 UTC148
                ErrorKind::RecoveryRejected
96fdf90aacd6atagen2026-09-08 08:24 UTC149
            }
96fdf90aacd6atagen2026-09-08 08:24 UTC150
        };
96fdf90aacd6atagen2026-09-08 08:24 UTC151
        Self::with_source(kind, message, source)
96fdf90aacd6atagen2026-09-08 08:24 UTC152
    }
96fdf90aacd6atagen2026-09-08 08:24 UTC153
96fdf90aacd6atagen2026-09-08 08:24 UTC154
    pub(crate) fn from_verification_request(
96fdf90aacd6atagen2026-09-08 08:24 UTC155
        message: impl Into<String>,
96fdf90aacd6atagen2026-09-08 08:24 UTC156
        source: RequestVerificationError,
96fdf90aacd6atagen2026-09-08 08:24 UTC157
    ) -> Self {
96fdf90aacd6atagen2026-09-08 08:24 UTC158
        let kind = match &source {
96fdf90aacd6atagen2026-09-08 08:24 UTC159
            RequestVerificationError::Sdk(source) => classify_sdk_error(source),
31ce2453c82fatagen2026-09-24 13:07 UTC160
            RequestVerificationError::RoomCreation(_) => ErrorKind::Encryption,
96fdf90aacd6atagen2026-09-08 08:24 UTC161
        };
96fdf90aacd6atagen2026-09-08 08:24 UTC162
        Self::with_source(kind, message, source)
96fdf90aacd6atagen2026-09-08 08:24 UTC163
    }
96fdf90aacd6atagen2026-09-08 08:24 UTC164
}
96fdf90aacd6atagen2026-09-08 08:24 UTC165
31ce2453c82fatagen2026-09-24 13:07 UTC166
impl PartialEq for Error {
31ce2453c82fatagen2026-09-24 13:07 UTC167
    fn eq(&self, other: &Self) -> bool {
31ce2453c82fatagen2026-09-24 13:07 UTC168
        self.kind == other.kind
31ce2453c82fatagen2026-09-24 13:07 UTC169
            && self.message == other.message
31ce2453c82fatagen2026-09-24 13:07 UTC170
            && self.challenge == other.challenge
31ce2453c82fatagen2026-09-24 13:07 UTC171
    }
31ce2453c82fatagen2026-09-24 13:07 UTC172
}
31ce2453c82fatagen2026-09-24 13:07 UTC173
31ce2453c82fatagen2026-09-24 13:07 UTC174
pub(crate) fn classify_sdk_error(source: &matrix_sdk::Error) -> ErrorKind {
96fdf90aacd6atagen2026-09-08 08:24 UTC175
    match source {
96fdf90aacd6atagen2026-09-08 08:24 UTC176
        matrix_sdk::Error::Http(source) => classify_http_error(source),
96fdf90aacd6atagen2026-09-08 08:24 UTC177
        matrix_sdk::Error::OAuth(source) => classify_oauth_error(source),
31ce2453c82fatagen2026-09-24 13:07 UTC178
        matrix_sdk::Error::AuthenticationRequired => ErrorKind::Unauthenticated,
96fdf90aacd6atagen2026-09-08 08:24 UTC179
        matrix_sdk::Error::BadCryptoStoreState
96fdf90aacd6atagen2026-09-08 08:24 UTC180
        | matrix_sdk::Error::CryptoStoreError(_)
96fdf90aacd6atagen2026-09-08 08:24 UTC181
        | matrix_sdk::Error::CrossProcessLockError(_)
96fdf90aacd6atagen2026-09-08 08:24 UTC182
        | matrix_sdk::Error::StateStore(_)
96fdf90aacd6atagen2026-09-08 08:24 UTC183
        | matrix_sdk::Error::EventCacheStore(_)
31ce2453c82fatagen2026-09-24 13:07 UTC184
        | matrix_sdk::Error::MediaStore(_) => ErrorKind::Store,
96fdf90aacd6atagen2026-09-08 08:24 UTC185
        matrix_sdk::Error::NoOlmMachine
96fdf90aacd6atagen2026-09-08 08:24 UTC186
        | matrix_sdk::Error::OlmError(_)
96fdf90aacd6atagen2026-09-08 08:24 UTC187
        | matrix_sdk::Error::MegolmError(_)
31ce2453c82fatagen2026-09-24 13:07 UTC188
        | matrix_sdk::Error::DecryptorError(_) => ErrorKind::Encryption,
31ce2453c82fatagen2026-09-24 13:07 UTC189
        matrix_sdk::Error::Media(_) => ErrorKind::MediaUnavailable,
31ce2453c82fatagen2026-09-24 13:07 UTC190
        matrix_sdk::Error::Timeout => ErrorKind::Network,
31ce2453c82fatagen2026-09-24 13:07 UTC191
        _ => ErrorKind::Other,
96fdf90aacd6atagen2026-09-08 08:24 UTC192
    }
96fdf90aacd6atagen2026-09-08 08:24 UTC193
}
96fdf90aacd6atagen2026-09-08 08:24 UTC194
31ce2453c82fatagen2026-09-24 13:07 UTC195
fn classify_http_error(source: &HttpError) -> ErrorKind {
96fdf90aacd6atagen2026-09-08 08:24 UTC196
    match source {
31ce2453c82fatagen2026-09-24 13:07 UTC197
        HttpError::Reqwest(_) => ErrorKind::Network,
31ce2453c82fatagen2026-09-24 13:07 UTC198
        HttpError::Api(_) => ErrorKind::Server,
96fdf90aacd6atagen2026-09-08 08:24 UTC199
        HttpError::RefreshToken(source) => classify_refresh_token_error(source),
96fdf90aacd6atagen2026-09-08 08:24 UTC200
        HttpError::Cached(source) => classify_http_error(source),
31ce2453c82fatagen2026-09-24 13:07 UTC201
        _ => ErrorKind::Other,
96fdf90aacd6atagen2026-09-08 08:24 UTC202
    }
96fdf90aacd6atagen2026-09-08 08:24 UTC203
}
96fdf90aacd6atagen2026-09-08 08:24 UTC204
31ce2453c82fatagen2026-09-24 13:07 UTC205
fn classify_refresh_token_error(source: &RefreshTokenError) -> ErrorKind {
96fdf90aacd6atagen2026-09-08 08:24 UTC206
    match source {
31ce2453c82fatagen2026-09-24 13:07 UTC207
        RefreshTokenError::RefreshTokenRequired => ErrorKind::Unauthenticated,
96fdf90aacd6atagen2026-09-08 08:24 UTC208
        RefreshTokenError::MatrixAuth(source) => classify_http_error(source),
96fdf90aacd6atagen2026-09-08 08:24 UTC209
        RefreshTokenError::OAuth(source) => classify_oauth_error(source),
96fdf90aacd6atagen2026-09-08 08:24 UTC210
    }
96fdf90aacd6atagen2026-09-08 08:24 UTC211
}
96fdf90aacd6atagen2026-09-08 08:24 UTC212
31ce2453c82fatagen2026-09-24 13:07 UTC213
fn classify_oauth_error(source: &OAuthError) -> ErrorKind {
96fdf90aacd6atagen2026-09-08 08:24 UTC214
    let classify_token_request_error = |source: &_| match source {
31ce2453c82fatagen2026-09-24 13:07 UTC215
        RequestTokenError::Request(_) => ErrorKind::Network,
31ce2453c82fatagen2026-09-24 13:07 UTC216
        RequestTokenError::ServerResponse(_) => ErrorKind::Unauthenticated,
31ce2453c82fatagen2026-09-24 13:07 UTC217
        _ => ErrorKind::Other,
96fdf90aacd6atagen2026-09-08 08:24 UTC218
    };
96fdf90aacd6atagen2026-09-08 08:24 UTC219
    match source {
96fdf90aacd6atagen2026-09-08 08:24 UTC220
        OAuthError::Discovery(source) => match source {
96fdf90aacd6atagen2026-09-08 08:24 UTC221
            OAuthDiscoveryError::Http(source) => classify_http_error(source),
96fdf90aacd6atagen2026-09-08 08:24 UTC222
            OAuthDiscoveryError::Oidc(source) => classify_token_request_error(source),
31ce2453c82fatagen2026-09-24 13:07 UTC223
            _ => ErrorKind::Unauthenticated,
96fdf90aacd6atagen2026-09-08 08:24 UTC224
        },
96fdf90aacd6atagen2026-09-08 08:24 UTC225
        OAuthError::RefreshToken(source) => classify_token_request_error(source),
96fdf90aacd6atagen2026-09-08 08:24 UTC226
        OAuthError::AuthorizationCode(OAuthAuthorizationCodeError::RequestToken(source)) => {
96fdf90aacd6atagen2026-09-08 08:24 UTC227
            classify_token_request_error(source)
96fdf90aacd6atagen2026-09-08 08:24 UTC228
        }
31ce2453c82fatagen2026-09-24 13:07 UTC229
        OAuthError::AuthorizationCode(_) => ErrorKind::Unauthenticated,
96fdf90aacd6atagen2026-09-08 08:24 UTC230
        OAuthError::Logout(source) => match source {
31ce2453c82fatagen2026-09-24 13:07 UTC231
            OAuthTokenRevocationError::Revoke(RequestTokenError::Request(_)) => ErrorKind::Network,
96fdf90aacd6atagen2026-09-08 08:24 UTC232
            OAuthTokenRevocationError::Revoke(RequestTokenError::ServerResponse(_)) => {
31ce2453c82fatagen2026-09-24 13:07 UTC233
                ErrorKind::Unauthenticated
96fdf90aacd6atagen2026-09-08 08:24 UTC234
            }
31ce2453c82fatagen2026-09-24 13:07 UTC235
            _ => ErrorKind::Other,
96fdf90aacd6atagen2026-09-08 08:24 UTC236
        },
31ce2453c82fatagen2026-09-24 13:07 UTC237
        _ => ErrorKind::Unauthenticated,
96fdf90aacd6atagen2026-09-08 08:24 UTC238
    }
96fdf90aacd6atagen2026-09-08 08:24 UTC239
}