atagen

macltok

public
Star0
Watch0
121a56ce119d97a65954edd1253f68cb6093d2a7
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::{
1fe480c16a3catagen2026-09-26 08:44 UTC4
    HttpError, RefreshTokenError, SendOutsideWasm, SyncOutsideWasm,
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
1fe480c16a3catagen2026-09-26 08:44 UTC20
/// the sdk's `SendOutsideWasm` isn't an auto trait, so it can't go in a trait object
1fe480c16a3catagen2026-09-26 08:44 UTC21
#[cfg(not(target_family = "wasm"))]
62fe32759529atagen2026-09-26 08:50 UTC22
pub(crate) type SourceError = dyn std::error::Error + Send + Sync;
1fe480c16a3catagen2026-09-26 08:44 UTC23
#[cfg(target_family = "wasm")]
62fe32759529atagen2026-09-26 08:50 UTC24
pub(crate) type SourceError = dyn std::error::Error;
1fe480c16a3catagen2026-09-26 08:44 UTC25
31ce2453c82fatagen2026-09-24 13:07 UTC26
/// the one thing that goes wrong, for commands and queries alike. match on `kind`, show `message`
31ce2453c82fatagen2026-09-24 13:07 UTC27
#[derive(Clone, Debug, thiserror::Error)]
31ce2453c82fatagen2026-09-24 13:07 UTC28
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
96fdf90aacd6atagen2026-09-08 08:24 UTC29
#[error("{message}")]
31ce2453c82fatagen2026-09-24 13:07 UTC30
#[non_exhaustive]
31ce2453c82fatagen2026-09-24 13:07 UTC31
pub struct Error {
31ce2453c82fatagen2026-09-24 13:07 UTC32
    pub kind: ErrorKind,
31ce2453c82fatagen2026-09-24 13:07 UTC33
    pub message: String,
31ce2453c82fatagen2026-09-24 13:07 UTC34
    /// set when the server wants interactive auth before it'll do the thing
31ce2453c82fatagen2026-09-24 13:07 UTC35
    pub challenge: Option<Box<InteractiveAuthChallenge>>,
9a25b6ce66f4atagen2026-10-08 11:15 UTC36
    /// set when the homeserver refused with a matrix error
9a25b6ce66f4atagen2026-10-08 11:15 UTC37
    pub server: Option<ServerError>,
96fdf90aacd6atagen2026-09-08 08:24 UTC38
    #[source]
31ce2453c82fatagen2026-09-24 13:07 UTC39
    #[cfg_attr(feature = "serde", serde(skip))]
1fe480c16a3catagen2026-09-26 08:44 UTC40
    source: Option<Arc<SourceError>>,
96fdf90aacd6atagen2026-09-08 08:24 UTC41
}
96fdf90aacd6atagen2026-09-08 08:24 UTC42
31ce2453c82fatagen2026-09-24 13:07 UTC43
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
31ce2453c82fatagen2026-09-24 13:07 UTC44
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
31ce2453c82fatagen2026-09-24 13:07 UTC45
#[non_exhaustive]
31ce2453c82fatagen2026-09-24 13:07 UTC46
pub enum ErrorKind {
31ce2453c82fatagen2026-09-24 13:07 UTC47
    /// the engine stopped, or the task doing the work died, before answering
31ce2453c82fatagen2026-09-24 13:07 UTC48
    Interrupted,
31ce2453c82fatagen2026-09-24 13:07 UTC49
    Unauthenticated,
31ce2453c82fatagen2026-09-24 13:07 UTC50
    InteractiveAuthRequired,
31ce2453c82fatagen2026-09-24 13:07 UTC51
    Invalid,
31ce2453c82fatagen2026-09-24 13:07 UTC52
    RoomUnknown,
31ce2453c82fatagen2026-09-24 13:07 UTC53
    RoomNotOpen,
31ce2453c82fatagen2026-09-24 13:07 UTC54
    TimelineNotOpen,
31ce2453c82fatagen2026-09-24 13:07 UTC55
    RoomBusy,
31ce2453c82fatagen2026-09-24 13:07 UTC56
    QueueFull,
31ce2453c82fatagen2026-09-24 13:07 UTC57
    EmptyBody,
31ce2453c82fatagen2026-09-24 13:07 UTC58
    MediaUnknown,
31ce2453c82fatagen2026-09-24 13:07 UTC59
    MediaTooLarge,
31ce2453c82fatagen2026-09-24 13:07 UTC60
    MediaUnavailable,
31ce2453c82fatagen2026-09-24 13:07 UTC61
    VerificationInactive,
31ce2453c82fatagen2026-09-24 13:07 UTC62
    VerificationUnsupported,
31ce2453c82fatagen2026-09-24 13:07 UTC63
    NoCrossSigningIdentity,
31ce2453c82fatagen2026-09-24 13:07 UTC64
    RecoveryRejected,
31ce2453c82fatagen2026-09-24 13:07 UTC65
    Network,
0291516d40b5atagen2026-10-22 08:31 UTC66
    /// the homeserver wants us to slow down. try again later
0291516d40b5atagen2026-10-22 08:31 UTC67
    RateLimited,
31ce2453c82fatagen2026-09-24 13:07 UTC68
    Server,
31ce2453c82fatagen2026-09-24 13:07 UTC69
    Store,
31ce2453c82fatagen2026-09-24 13:07 UTC70
    Timeline,
31ce2453c82fatagen2026-09-24 13:07 UTC71
    Encryption,
31ce2453c82fatagen2026-09-24 13:07 UTC72
    Other,
31ce2453c82fatagen2026-09-24 13:07 UTC73
}
31ce2453c82fatagen2026-09-24 13:07 UTC74
9a25b6ce66f4atagen2026-10-08 11:15 UTC75
/// the homeserver's own answer, worth showing a person as it stands
9a25b6ce66f4atagen2026-10-08 11:15 UTC76
#[derive(Clone, Debug, Eq, PartialEq)]
9a25b6ce66f4atagen2026-10-08 11:15 UTC77
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9a25b6ce66f4atagen2026-10-08 11:15 UTC78
#[non_exhaustive]
9a25b6ce66f4atagen2026-10-08 11:15 UTC79
pub struct ServerError {
9a25b6ce66f4atagen2026-10-08 11:15 UTC80
    pub status: u16,
9a25b6ce66f4atagen2026-10-08 11:15 UTC81
    pub errcode: String,
9a25b6ce66f4atagen2026-10-08 11:15 UTC82
    pub message: String,
9a25b6ce66f4atagen2026-10-08 11:15 UTC83
}
9a25b6ce66f4atagen2026-10-08 11:15 UTC84
9a25b6ce66f4atagen2026-10-08 11:15 UTC85
impl ServerError {
9a25b6ce66f4atagen2026-10-08 11:15 UTC86
    pub(crate) fn find(source: &(dyn std::error::Error + 'static)) -> Option<Self> {
9a25b6ce66f4atagen2026-10-08 11:15 UTC87
        let mut current = Some(source);
9a25b6ce66f4atagen2026-10-08 11:15 UTC88
        while let Some(error) = current {
9a25b6ce66f4atagen2026-10-08 11:15 UTC89
            let api = if let Some(error) = error.downcast_ref::<matrix_sdk::Error>() {
9a25b6ce66f4atagen2026-10-08 11:15 UTC90
                error.as_client_api_error()
9a25b6ce66f4atagen2026-10-08 11:15 UTC91
            } else if let Some(error) = error.downcast_ref::<HttpError>() {
9a25b6ce66f4atagen2026-10-08 11:15 UTC92
                error.as_client_api_error()
9a25b6ce66f4atagen2026-10-08 11:15 UTC93
            } else {
9a25b6ce66f4atagen2026-10-08 11:15 UTC94
                error.downcast_ref::<ruma::api::error::Error>()
9a25b6ce66f4atagen2026-10-08 11:15 UTC95
            };
9a25b6ce66f4atagen2026-10-08 11:15 UTC96
            if let Some(api) = api
9a25b6ce66f4atagen2026-10-08 11:15 UTC97
                && let ruma::api::error::ErrorBody::Standard(body) = &api.body
9a25b6ce66f4atagen2026-10-08 11:15 UTC98
            {
9a25b6ce66f4atagen2026-10-08 11:15 UTC99
                return Some(Self {
9a25b6ce66f4atagen2026-10-08 11:15 UTC100
                    status: api.status_code.as_u16(),
9a25b6ce66f4atagen2026-10-08 11:15 UTC101
                    errcode: body.kind.errcode().to_string(),
9a25b6ce66f4atagen2026-10-08 11:15 UTC102
                    message: body.message.clone(),
9a25b6ce66f4atagen2026-10-08 11:15 UTC103
                });
9a25b6ce66f4atagen2026-10-08 11:15 UTC104
            }
9a25b6ce66f4atagen2026-10-08 11:15 UTC105
            current = error.source();
9a25b6ce66f4atagen2026-10-08 11:15 UTC106
        }
9a25b6ce66f4atagen2026-10-08 11:15 UTC107
        None
9a25b6ce66f4atagen2026-10-08 11:15 UTC108
    }
9a25b6ce66f4atagen2026-10-08 11:15 UTC109
}
9a25b6ce66f4atagen2026-10-08 11:15 UTC110
9a25b6ce66f4atagen2026-10-08 11:15 UTC111
impl std::fmt::Display for ServerError {
9a25b6ce66f4atagen2026-10-08 11:15 UTC112
    fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
9a25b6ce66f4atagen2026-10-08 11:15 UTC113
        write!(formatter, "{} ({})", self.message, self.errcode)
9a25b6ce66f4atagen2026-10-08 11:15 UTC114
    }
9a25b6ce66f4atagen2026-10-08 11:15 UTC115
}
9a25b6ce66f4atagen2026-10-08 11:15 UTC116
9a25b6ce66f4atagen2026-10-08 11:15 UTC117
#[cfg(any(feature = "sqlite", feature = "indexeddb"))]
9a25b6ce66f4atagen2026-10-08 11:15 UTC118
pub(crate) fn classify(source: &(dyn std::error::Error + 'static)) -> ErrorKind {
9a25b6ce66f4atagen2026-10-08 11:15 UTC119
    let mut current = Some(source);
9a25b6ce66f4atagen2026-10-08 11:15 UTC120
    while let Some(error) = current {
9a25b6ce66f4atagen2026-10-08 11:15 UTC121
        if let Some(error) = error.downcast_ref::<matrix_sdk::Error>() {
9a25b6ce66f4atagen2026-10-08 11:15 UTC122
            return classify_sdk_error(error);
9a25b6ce66f4atagen2026-10-08 11:15 UTC123
        }
9a25b6ce66f4atagen2026-10-08 11:15 UTC124
        if let Some(error) = error.downcast_ref::<HttpError>() {
9a25b6ce66f4atagen2026-10-08 11:15 UTC125
            return classify_http_error(error);
9a25b6ce66f4atagen2026-10-08 11:15 UTC126
        }
9a25b6ce66f4atagen2026-10-08 11:15 UTC127
        if let Some(error) = error.downcast_ref::<OAuthError>() {
9a25b6ce66f4atagen2026-10-08 11:15 UTC128
            return classify_oauth_error(error);
9a25b6ce66f4atagen2026-10-08 11:15 UTC129
        }
9a25b6ce66f4atagen2026-10-08 11:15 UTC130
        if let Some(error) = error.downcast_ref::<RefreshTokenError>() {
9a25b6ce66f4atagen2026-10-08 11:15 UTC131
            return classify_refresh_token_error(error);
9a25b6ce66f4atagen2026-10-08 11:15 UTC132
        }
9a25b6ce66f4atagen2026-10-08 11:15 UTC133
        current = error.source();
9a25b6ce66f4atagen2026-10-08 11:15 UTC134
    }
9a25b6ce66f4atagen2026-10-08 11:15 UTC135
    ErrorKind::Other
9a25b6ce66f4atagen2026-10-08 11:15 UTC136
}
9a25b6ce66f4atagen2026-10-08 11:15 UTC137
31ce2453c82fatagen2026-09-24 13:07 UTC138
impl Error {
31ce2453c82fatagen2026-09-24 13:07 UTC139
    pub(crate) fn new(kind: ErrorKind, message: impl Into<String>) -> Self {
96fdf90aacd6atagen2026-09-08 08:24 UTC140
        Self {
96fdf90aacd6atagen2026-09-08 08:24 UTC141
            kind,
96fdf90aacd6atagen2026-09-08 08:24 UTC142
            message: message.into(),
31ce2453c82fatagen2026-09-24 13:07 UTC143
            challenge: None,
9a25b6ce66f4atagen2026-10-08 11:15 UTC144
            server: None,
96fdf90aacd6atagen2026-09-08 08:24 UTC145
            source: None,
96fdf90aacd6atagen2026-09-08 08:24 UTC146
        }
96fdf90aacd6atagen2026-09-08 08:24 UTC147
    }
96fdf90aacd6atagen2026-09-08 08:24 UTC148
96fdf90aacd6atagen2026-09-08 08:24 UTC149
    pub(crate) fn with_source(
31ce2453c82fatagen2026-09-24 13:07 UTC150
        kind: ErrorKind,
96fdf90aacd6atagen2026-09-08 08:24 UTC151
        message: impl Into<String>,
1fe480c16a3catagen2026-09-26 08:44 UTC152
        source: impl std::error::Error + SendOutsideWasm + SyncOutsideWasm + 'static,
96fdf90aacd6atagen2026-09-08 08:24 UTC153
    ) -> Self {
96fdf90aacd6atagen2026-09-08 08:24 UTC154
        Self {
9a25b6ce66f4atagen2026-10-08 11:15 UTC155
            server: ServerError::find(&source),
31ce2453c82fatagen2026-09-24 13:07 UTC156
            source: Some(Arc::new(source)),
31ce2453c82fatagen2026-09-24 13:07 UTC157
            ..Self::new(kind, message)
31ce2453c82fatagen2026-09-24 13:07 UTC158
        }
31ce2453c82fatagen2026-09-24 13:07 UTC159
    }
31ce2453c82fatagen2026-09-24 13:07 UTC160
31ce2453c82fatagen2026-09-24 13:07 UTC161
    pub(crate) fn interrupted() -> Self {
31ce2453c82fatagen2026-09-24 13:07 UTC162
        Self::new(
31ce2453c82fatagen2026-09-24 13:07 UTC163
            ErrorKind::Interrupted,
31ce2453c82fatagen2026-09-24 13:07 UTC164
            "the engine stopped before the operation finished",
31ce2453c82fatagen2026-09-24 13:07 UTC165
        )
31ce2453c82fatagen2026-09-24 13:07 UTC166
    }
31ce2453c82fatagen2026-09-24 13:07 UTC167
31ce2453c82fatagen2026-09-24 13:07 UTC168
    pub(crate) fn room_unknown() -> Self {
31ce2453c82fatagen2026-09-24 13:07 UTC169
        Self::new(
31ce2453c82fatagen2026-09-24 13:07 UTC170
            ErrorKind::RoomUnknown,
31ce2453c82fatagen2026-09-24 13:07 UTC171
            "room is not available in the local store",
31ce2453c82fatagen2026-09-24 13:07 UTC172
        )
31ce2453c82fatagen2026-09-24 13:07 UTC173
    }
31ce2453c82fatagen2026-09-24 13:07 UTC174
31ce2453c82fatagen2026-09-24 13:07 UTC175
    pub(crate) fn interactive_auth(challenge: InteractiveAuthChallenge) -> Self {
31ce2453c82fatagen2026-09-24 13:07 UTC176
        Self {
31ce2453c82fatagen2026-09-24 13:07 UTC177
            challenge: Some(Box::new(challenge)),
31ce2453c82fatagen2026-09-24 13:07 UTC178
            ..Self::new(
31ce2453c82fatagen2026-09-24 13:07 UTC179
                ErrorKind::InteractiveAuthRequired,
31ce2453c82fatagen2026-09-24 13:07 UTC180
                "interactive authentication is required",
31ce2453c82fatagen2026-09-24 13:07 UTC181
            )
96fdf90aacd6atagen2026-09-08 08:24 UTC182
        }
96fdf90aacd6atagen2026-09-08 08:24 UTC183
    }
96fdf90aacd6atagen2026-09-08 08:24 UTC184
96fdf90aacd6atagen2026-09-08 08:24 UTC185
    pub(crate) fn from_sdk(message: impl Into<String>, source: matrix_sdk::Error) -> Self {
96fdf90aacd6atagen2026-09-08 08:24 UTC186
        Self::with_source(classify_sdk_error(&source), message, source)
96fdf90aacd6atagen2026-09-08 08:24 UTC187
    }
96fdf90aacd6atagen2026-09-08 08:24 UTC188
96fdf90aacd6atagen2026-09-08 08:24 UTC189
    pub(crate) fn from_http(message: impl Into<String>, source: HttpError) -> Self {
96fdf90aacd6atagen2026-09-08 08:24 UTC190
        Self::with_source(classify_http_error(&source), message, source)
96fdf90aacd6atagen2026-09-08 08:24 UTC191
    }
31ce2453c82fatagen2026-09-24 13:07 UTC192
96fdf90aacd6atagen2026-09-08 08:24 UTC193
    pub(crate) fn from_refresh_token(
96fdf90aacd6atagen2026-09-08 08:24 UTC194
        message: impl Into<String>,
96fdf90aacd6atagen2026-09-08 08:24 UTC195
        source: RefreshTokenError,
96fdf90aacd6atagen2026-09-08 08:24 UTC196
    ) -> Self {
96fdf90aacd6atagen2026-09-08 08:24 UTC197
        Self::with_source(classify_refresh_token_error(&source), message, source)
96fdf90aacd6atagen2026-09-08 08:24 UTC198
    }
96fdf90aacd6atagen2026-09-08 08:24 UTC199
96fdf90aacd6atagen2026-09-08 08:24 UTC200
    pub(crate) fn from_recovery(message: impl Into<String>, source: RecoveryError) -> Self {
96fdf90aacd6atagen2026-09-08 08:24 UTC201
        let kind = match &source {
96fdf90aacd6atagen2026-09-08 08:24 UTC202
            RecoveryError::Sdk(source) => classify_sdk_error(source),
96fdf90aacd6atagen2026-09-08 08:24 UTC203
            RecoveryError::SecretStorage(SecretStorageError::Sdk(source)) => {
96fdf90aacd6atagen2026-09-08 08:24 UTC204
                classify_sdk_error(source)
96fdf90aacd6atagen2026-09-08 08:24 UTC205
            }
96fdf90aacd6atagen2026-09-08 08:24 UTC206
            RecoveryError::SecretStorage(SecretStorageError::ImportError { error, .. }) => {
96fdf90aacd6atagen2026-09-08 08:24 UTC207
                match error {
96fdf90aacd6atagen2026-09-08 08:24 UTC208
                    ImportError::Sdk(source) => classify_sdk_error(source),
31ce2453c82fatagen2026-09-24 13:07 UTC209
                    _ => ErrorKind::RecoveryRejected,
96fdf90aacd6atagen2026-09-08 08:24 UTC210
                }
96fdf90aacd6atagen2026-09-08 08:24 UTC211
            }
96fdf90aacd6atagen2026-09-08 08:24 UTC212
            RecoveryError::SecretStorage(SecretStorageError::Verification(source)) => {
96fdf90aacd6atagen2026-09-08 08:24 UTC213
                match source {
96fdf90aacd6atagen2026-09-08 08:24 UTC214
                    ManualVerifyError::Http(source) => classify_http_error(source),
31ce2453c82fatagen2026-09-24 13:07 UTC215
                    _ => ErrorKind::RecoveryRejected,
96fdf90aacd6atagen2026-09-08 08:24 UTC216
                }
96fdf90aacd6atagen2026-09-08 08:24 UTC217
            }
96fdf90aacd6atagen2026-09-08 08:24 UTC218
            RecoveryError::SecretStorage(SecretStorageError::SecretStorageKey(_)) => {
31ce2453c82fatagen2026-09-24 13:07 UTC219
                ErrorKind::RecoveryRejected
96fdf90aacd6atagen2026-09-08 08:24 UTC220
            }
31ce2453c82fatagen2026-09-24 13:07 UTC221
            RecoveryError::SecretStorage(SecretStorageError::Storage(_)) => ErrorKind::Store,
96fdf90aacd6atagen2026-09-08 08:24 UTC222
            RecoveryError::BackupExistsOnServer | RecoveryError::SecretStorage(_) => {
31ce2453c82fatagen2026-09-24 13:07 UTC223
                ErrorKind::RecoveryRejected
96fdf90aacd6atagen2026-09-08 08:24 UTC224
            }
96fdf90aacd6atagen2026-09-08 08:24 UTC225
        };
96fdf90aacd6atagen2026-09-08 08:24 UTC226
        Self::with_source(kind, message, source)
96fdf90aacd6atagen2026-09-08 08:24 UTC227
    }
96fdf90aacd6atagen2026-09-08 08:24 UTC228
96fdf90aacd6atagen2026-09-08 08:24 UTC229
    pub(crate) fn from_verification_request(
96fdf90aacd6atagen2026-09-08 08:24 UTC230
        message: impl Into<String>,
96fdf90aacd6atagen2026-09-08 08:24 UTC231
        source: RequestVerificationError,
96fdf90aacd6atagen2026-09-08 08:24 UTC232
    ) -> Self {
96fdf90aacd6atagen2026-09-08 08:24 UTC233
        let kind = match &source {
96fdf90aacd6atagen2026-09-08 08:24 UTC234
            RequestVerificationError::Sdk(source) => classify_sdk_error(source),
31ce2453c82fatagen2026-09-24 13:07 UTC235
            RequestVerificationError::RoomCreation(_) => ErrorKind::Encryption,
96fdf90aacd6atagen2026-09-08 08:24 UTC236
        };
96fdf90aacd6atagen2026-09-08 08:24 UTC237
        Self::with_source(kind, message, source)
96fdf90aacd6atagen2026-09-08 08:24 UTC238
    }
96fdf90aacd6atagen2026-09-08 08:24 UTC239
}
96fdf90aacd6atagen2026-09-08 08:24 UTC240
31ce2453c82fatagen2026-09-24 13:07 UTC241
impl PartialEq for Error {
31ce2453c82fatagen2026-09-24 13:07 UTC242
    fn eq(&self, other: &Self) -> bool {
31ce2453c82fatagen2026-09-24 13:07 UTC243
        self.kind == other.kind
31ce2453c82fatagen2026-09-24 13:07 UTC244
            && self.message == other.message
31ce2453c82fatagen2026-09-24 13:07 UTC245
            && self.challenge == other.challenge
9a25b6ce66f4atagen2026-10-08 11:15 UTC246
            && self.server == other.server
31ce2453c82fatagen2026-09-24 13:07 UTC247
    }
31ce2453c82fatagen2026-09-24 13:07 UTC248
}
31ce2453c82fatagen2026-09-24 13:07 UTC249
31ce2453c82fatagen2026-09-24 13:07 UTC250
pub(crate) fn classify_sdk_error(source: &matrix_sdk::Error) -> ErrorKind {
96fdf90aacd6atagen2026-09-08 08:24 UTC251
    match source {
96fdf90aacd6atagen2026-09-08 08:24 UTC252
        matrix_sdk::Error::Http(source) => classify_http_error(source),
96fdf90aacd6atagen2026-09-08 08:24 UTC253
        matrix_sdk::Error::OAuth(source) => classify_oauth_error(source),
31ce2453c82fatagen2026-09-24 13:07 UTC254
        matrix_sdk::Error::AuthenticationRequired => ErrorKind::Unauthenticated,
96fdf90aacd6atagen2026-09-08 08:24 UTC255
        matrix_sdk::Error::BadCryptoStoreState
96fdf90aacd6atagen2026-09-08 08:24 UTC256
        | matrix_sdk::Error::CryptoStoreError(_)
96fdf90aacd6atagen2026-09-08 08:24 UTC257
        | matrix_sdk::Error::CrossProcessLockError(_)
96fdf90aacd6atagen2026-09-08 08:24 UTC258
        | matrix_sdk::Error::StateStore(_)
96fdf90aacd6atagen2026-09-08 08:24 UTC259
        | matrix_sdk::Error::EventCacheStore(_)
31ce2453c82fatagen2026-09-24 13:07 UTC260
        | matrix_sdk::Error::MediaStore(_) => ErrorKind::Store,
96fdf90aacd6atagen2026-09-08 08:24 UTC261
        matrix_sdk::Error::NoOlmMachine
96fdf90aacd6atagen2026-09-08 08:24 UTC262
        | matrix_sdk::Error::OlmError(_)
96fdf90aacd6atagen2026-09-08 08:24 UTC263
        | matrix_sdk::Error::MegolmError(_)
31ce2453c82fatagen2026-09-24 13:07 UTC264
        | matrix_sdk::Error::DecryptorError(_) => ErrorKind::Encryption,
31ce2453c82fatagen2026-09-24 13:07 UTC265
        matrix_sdk::Error::Media(_) => ErrorKind::MediaUnavailable,
31ce2453c82fatagen2026-09-24 13:07 UTC266
        matrix_sdk::Error::Timeout => ErrorKind::Network,
31ce2453c82fatagen2026-09-24 13:07 UTC267
        _ => ErrorKind::Other,
96fdf90aacd6atagen2026-09-08 08:24 UTC268
    }
96fdf90aacd6atagen2026-09-08 08:24 UTC269
}
96fdf90aacd6atagen2026-09-08 08:24 UTC270
31ce2453c82fatagen2026-09-24 13:07 UTC271
fn classify_http_error(source: &HttpError) -> ErrorKind {
96fdf90aacd6atagen2026-09-08 08:24 UTC272
    match source {
31ce2453c82fatagen2026-09-24 13:07 UTC273
        HttpError::Reqwest(_) => ErrorKind::Network,
0291516d40b5atagen2026-10-22 08:31 UTC274
        HttpError::Api(_)
0291516d40b5atagen2026-10-22 08:31 UTC275
            if source
0291516d40b5atagen2026-10-22 08:31 UTC276
                .as_client_api_error()
0291516d40b5atagen2026-10-22 08:31 UTC277
                .is_some_and(|api| api.status_code.as_u16() == 429) =>
0291516d40b5atagen2026-10-22 08:31 UTC278
        {
0291516d40b5atagen2026-10-22 08:31 UTC279
            ErrorKind::RateLimited
0291516d40b5atagen2026-10-22 08:31 UTC280
        }
31ce2453c82fatagen2026-09-24 13:07 UTC281
        HttpError::Api(_) => ErrorKind::Server,
96fdf90aacd6atagen2026-09-08 08:24 UTC282
        HttpError::RefreshToken(source) => classify_refresh_token_error(source),
96fdf90aacd6atagen2026-09-08 08:24 UTC283
        HttpError::Cached(source) => classify_http_error(source),
31ce2453c82fatagen2026-09-24 13:07 UTC284
        _ => ErrorKind::Other,
96fdf90aacd6atagen2026-09-08 08:24 UTC285
    }
96fdf90aacd6atagen2026-09-08 08:24 UTC286
}
96fdf90aacd6atagen2026-09-08 08:24 UTC287
31ce2453c82fatagen2026-09-24 13:07 UTC288
fn classify_refresh_token_error(source: &RefreshTokenError) -> ErrorKind {
96fdf90aacd6atagen2026-09-08 08:24 UTC289
    match source {
31ce2453c82fatagen2026-09-24 13:07 UTC290
        RefreshTokenError::RefreshTokenRequired => ErrorKind::Unauthenticated,
96fdf90aacd6atagen2026-09-08 08:24 UTC291
        RefreshTokenError::MatrixAuth(source) => classify_http_error(source),
96fdf90aacd6atagen2026-09-08 08:24 UTC292
        RefreshTokenError::OAuth(source) => classify_oauth_error(source),
96fdf90aacd6atagen2026-09-08 08:24 UTC293
    }
96fdf90aacd6atagen2026-09-08 08:24 UTC294
}
96fdf90aacd6atagen2026-09-08 08:24 UTC295
31ce2453c82fatagen2026-09-24 13:07 UTC296
fn classify_oauth_error(source: &OAuthError) -> ErrorKind {
96fdf90aacd6atagen2026-09-08 08:24 UTC297
    let classify_token_request_error = |source: &_| match source {
31ce2453c82fatagen2026-09-24 13:07 UTC298
        RequestTokenError::Request(_) => ErrorKind::Network,
31ce2453c82fatagen2026-09-24 13:07 UTC299
        RequestTokenError::ServerResponse(_) => ErrorKind::Unauthenticated,
31ce2453c82fatagen2026-09-24 13:07 UTC300
        _ => ErrorKind::Other,
96fdf90aacd6atagen2026-09-08 08:24 UTC301
    };
96fdf90aacd6atagen2026-09-08 08:24 UTC302
    match source {
96fdf90aacd6atagen2026-09-08 08:24 UTC303
        OAuthError::Discovery(source) => match source {
96fdf90aacd6atagen2026-09-08 08:24 UTC304
            OAuthDiscoveryError::Http(source) => classify_http_error(source),
96fdf90aacd6atagen2026-09-08 08:24 UTC305
            OAuthDiscoveryError::Oidc(source) => classify_token_request_error(source),
31ce2453c82fatagen2026-09-24 13:07 UTC306
            _ => ErrorKind::Unauthenticated,
96fdf90aacd6atagen2026-09-08 08:24 UTC307
        },
96fdf90aacd6atagen2026-09-08 08:24 UTC308
        OAuthError::RefreshToken(source) => classify_token_request_error(source),
96fdf90aacd6atagen2026-09-08 08:24 UTC309
        OAuthError::AuthorizationCode(OAuthAuthorizationCodeError::RequestToken(source)) => {
96fdf90aacd6atagen2026-09-08 08:24 UTC310
            classify_token_request_error(source)
96fdf90aacd6atagen2026-09-08 08:24 UTC311
        }
31ce2453c82fatagen2026-09-24 13:07 UTC312
        OAuthError::AuthorizationCode(_) => ErrorKind::Unauthenticated,
96fdf90aacd6atagen2026-09-08 08:24 UTC313
        OAuthError::Logout(source) => match source {
31ce2453c82fatagen2026-09-24 13:07 UTC314
            OAuthTokenRevocationError::Revoke(RequestTokenError::Request(_)) => ErrorKind::Network,
96fdf90aacd6atagen2026-09-08 08:24 UTC315
            OAuthTokenRevocationError::Revoke(RequestTokenError::ServerResponse(_)) => {
31ce2453c82fatagen2026-09-24 13:07 UTC316
                ErrorKind::Unauthenticated
96fdf90aacd6atagen2026-09-08 08:24 UTC317
            }
31ce2453c82fatagen2026-09-24 13:07 UTC318
            _ => ErrorKind::Other,
96fdf90aacd6atagen2026-09-08 08:24 UTC319
        },
31ce2453c82fatagen2026-09-24 13:07 UTC320
        _ => ErrorKind::Unauthenticated,
96fdf90aacd6atagen2026-09-08 08:24 UTC321
    }
96fdf90aacd6atagen2026-09-08 08:24 UTC322
}