atagen

macltok

public
Star0
Watch0
cb0668d30c14c14e0b1edddc9133ebf1e98bd5cb
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,
31ce2453c82fatagen2026-09-24 13:07 UTC66
    Server,
31ce2453c82fatagen2026-09-24 13:07 UTC67
    Store,
31ce2453c82fatagen2026-09-24 13:07 UTC68
    Timeline,
31ce2453c82fatagen2026-09-24 13:07 UTC69
    Encryption,
31ce2453c82fatagen2026-09-24 13:07 UTC70
    Other,
31ce2453c82fatagen2026-09-24 13:07 UTC71
}
31ce2453c82fatagen2026-09-24 13:07 UTC72
9a25b6ce66f4atagen2026-10-08 11:15 UTC73
/// the homeserver's own answer, worth showing a person as it stands
9a25b6ce66f4atagen2026-10-08 11:15 UTC74
#[derive(Clone, Debug, Eq, PartialEq)]
9a25b6ce66f4atagen2026-10-08 11:15 UTC75
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9a25b6ce66f4atagen2026-10-08 11:15 UTC76
#[non_exhaustive]
9a25b6ce66f4atagen2026-10-08 11:15 UTC77
pub struct ServerError {
9a25b6ce66f4atagen2026-10-08 11:15 UTC78
    pub status: u16,
9a25b6ce66f4atagen2026-10-08 11:15 UTC79
    pub errcode: String,
9a25b6ce66f4atagen2026-10-08 11:15 UTC80
    pub message: String,
9a25b6ce66f4atagen2026-10-08 11:15 UTC81
}
9a25b6ce66f4atagen2026-10-08 11:15 UTC82
9a25b6ce66f4atagen2026-10-08 11:15 UTC83
impl ServerError {
9a25b6ce66f4atagen2026-10-08 11:15 UTC84
    pub(crate) fn find(source: &(dyn std::error::Error + 'static)) -> Option<Self> {
9a25b6ce66f4atagen2026-10-08 11:15 UTC85
        let mut current = Some(source);
9a25b6ce66f4atagen2026-10-08 11:15 UTC86
        while let Some(error) = current {
9a25b6ce66f4atagen2026-10-08 11:15 UTC87
            let api = if let Some(error) = error.downcast_ref::<matrix_sdk::Error>() {
9a25b6ce66f4atagen2026-10-08 11:15 UTC88
                error.as_client_api_error()
9a25b6ce66f4atagen2026-10-08 11:15 UTC89
            } else if let Some(error) = error.downcast_ref::<HttpError>() {
9a25b6ce66f4atagen2026-10-08 11:15 UTC90
                error.as_client_api_error()
9a25b6ce66f4atagen2026-10-08 11:15 UTC91
            } else {
9a25b6ce66f4atagen2026-10-08 11:15 UTC92
                error.downcast_ref::<ruma::api::error::Error>()
9a25b6ce66f4atagen2026-10-08 11:15 UTC93
            };
9a25b6ce66f4atagen2026-10-08 11:15 UTC94
            if let Some(api) = api
9a25b6ce66f4atagen2026-10-08 11:15 UTC95
                && let ruma::api::error::ErrorBody::Standard(body) = &api.body
9a25b6ce66f4atagen2026-10-08 11:15 UTC96
            {
9a25b6ce66f4atagen2026-10-08 11:15 UTC97
                return Some(Self {
9a25b6ce66f4atagen2026-10-08 11:15 UTC98
                    status: api.status_code.as_u16(),
9a25b6ce66f4atagen2026-10-08 11:15 UTC99
                    errcode: body.kind.errcode().to_string(),
9a25b6ce66f4atagen2026-10-08 11:15 UTC100
                    message: body.message.clone(),
9a25b6ce66f4atagen2026-10-08 11:15 UTC101
                });
9a25b6ce66f4atagen2026-10-08 11:15 UTC102
            }
9a25b6ce66f4atagen2026-10-08 11:15 UTC103
            current = error.source();
9a25b6ce66f4atagen2026-10-08 11:15 UTC104
        }
9a25b6ce66f4atagen2026-10-08 11:15 UTC105
        None
9a25b6ce66f4atagen2026-10-08 11:15 UTC106
    }
9a25b6ce66f4atagen2026-10-08 11:15 UTC107
}
9a25b6ce66f4atagen2026-10-08 11:15 UTC108
9a25b6ce66f4atagen2026-10-08 11:15 UTC109
impl std::fmt::Display for ServerError {
9a25b6ce66f4atagen2026-10-08 11:15 UTC110
    fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
9a25b6ce66f4atagen2026-10-08 11:15 UTC111
        write!(formatter, "{} ({})", self.message, self.errcode)
9a25b6ce66f4atagen2026-10-08 11:15 UTC112
    }
9a25b6ce66f4atagen2026-10-08 11:15 UTC113
}
9a25b6ce66f4atagen2026-10-08 11:15 UTC114
9a25b6ce66f4atagen2026-10-08 11:15 UTC115
#[cfg(any(feature = "sqlite", feature = "indexeddb"))]
9a25b6ce66f4atagen2026-10-08 11:15 UTC116
pub(crate) fn classify(source: &(dyn std::error::Error + 'static)) -> ErrorKind {
9a25b6ce66f4atagen2026-10-08 11:15 UTC117
    let mut current = Some(source);
9a25b6ce66f4atagen2026-10-08 11:15 UTC118
    while let Some(error) = current {
9a25b6ce66f4atagen2026-10-08 11:15 UTC119
        if let Some(error) = error.downcast_ref::<matrix_sdk::Error>() {
9a25b6ce66f4atagen2026-10-08 11:15 UTC120
            return classify_sdk_error(error);
9a25b6ce66f4atagen2026-10-08 11:15 UTC121
        }
9a25b6ce66f4atagen2026-10-08 11:15 UTC122
        if let Some(error) = error.downcast_ref::<HttpError>() {
9a25b6ce66f4atagen2026-10-08 11:15 UTC123
            return classify_http_error(error);
9a25b6ce66f4atagen2026-10-08 11:15 UTC124
        }
9a25b6ce66f4atagen2026-10-08 11:15 UTC125
        if let Some(error) = error.downcast_ref::<OAuthError>() {
9a25b6ce66f4atagen2026-10-08 11:15 UTC126
            return classify_oauth_error(error);
9a25b6ce66f4atagen2026-10-08 11:15 UTC127
        }
9a25b6ce66f4atagen2026-10-08 11:15 UTC128
        if let Some(error) = error.downcast_ref::<RefreshTokenError>() {
9a25b6ce66f4atagen2026-10-08 11:15 UTC129
            return classify_refresh_token_error(error);
9a25b6ce66f4atagen2026-10-08 11:15 UTC130
        }
9a25b6ce66f4atagen2026-10-08 11:15 UTC131
        current = error.source();
9a25b6ce66f4atagen2026-10-08 11:15 UTC132
    }
9a25b6ce66f4atagen2026-10-08 11:15 UTC133
    ErrorKind::Other
9a25b6ce66f4atagen2026-10-08 11:15 UTC134
}
9a25b6ce66f4atagen2026-10-08 11:15 UTC135
31ce2453c82fatagen2026-09-24 13:07 UTC136
impl Error {
31ce2453c82fatagen2026-09-24 13:07 UTC137
    pub(crate) fn new(kind: ErrorKind, message: impl Into<String>) -> Self {
96fdf90aacd6atagen2026-09-08 08:24 UTC138
        Self {
96fdf90aacd6atagen2026-09-08 08:24 UTC139
            kind,
96fdf90aacd6atagen2026-09-08 08:24 UTC140
            message: message.into(),
31ce2453c82fatagen2026-09-24 13:07 UTC141
            challenge: None,
9a25b6ce66f4atagen2026-10-08 11:15 UTC142
            server: None,
96fdf90aacd6atagen2026-09-08 08:24 UTC143
            source: None,
96fdf90aacd6atagen2026-09-08 08:24 UTC144
        }
96fdf90aacd6atagen2026-09-08 08:24 UTC145
    }
96fdf90aacd6atagen2026-09-08 08:24 UTC146
96fdf90aacd6atagen2026-09-08 08:24 UTC147
    pub(crate) fn with_source(
31ce2453c82fatagen2026-09-24 13:07 UTC148
        kind: ErrorKind,
96fdf90aacd6atagen2026-09-08 08:24 UTC149
        message: impl Into<String>,
1fe480c16a3catagen2026-09-26 08:44 UTC150
        source: impl std::error::Error + SendOutsideWasm + SyncOutsideWasm + 'static,
96fdf90aacd6atagen2026-09-08 08:24 UTC151
    ) -> Self {
96fdf90aacd6atagen2026-09-08 08:24 UTC152
        Self {
9a25b6ce66f4atagen2026-10-08 11:15 UTC153
            server: ServerError::find(&source),
31ce2453c82fatagen2026-09-24 13:07 UTC154
            source: Some(Arc::new(source)),
31ce2453c82fatagen2026-09-24 13:07 UTC155
            ..Self::new(kind, message)
31ce2453c82fatagen2026-09-24 13:07 UTC156
        }
31ce2453c82fatagen2026-09-24 13:07 UTC157
    }
31ce2453c82fatagen2026-09-24 13:07 UTC158
31ce2453c82fatagen2026-09-24 13:07 UTC159
    pub(crate) fn interrupted() -> Self {
31ce2453c82fatagen2026-09-24 13:07 UTC160
        Self::new(
31ce2453c82fatagen2026-09-24 13:07 UTC161
            ErrorKind::Interrupted,
31ce2453c82fatagen2026-09-24 13:07 UTC162
            "the engine stopped before the operation finished",
31ce2453c82fatagen2026-09-24 13:07 UTC163
        )
31ce2453c82fatagen2026-09-24 13:07 UTC164
    }
31ce2453c82fatagen2026-09-24 13:07 UTC165
31ce2453c82fatagen2026-09-24 13:07 UTC166
    pub(crate) fn room_unknown() -> Self {
31ce2453c82fatagen2026-09-24 13:07 UTC167
        Self::new(
31ce2453c82fatagen2026-09-24 13:07 UTC168
            ErrorKind::RoomUnknown,
31ce2453c82fatagen2026-09-24 13:07 UTC169
            "room is not available in the local store",
31ce2453c82fatagen2026-09-24 13:07 UTC170
        )
31ce2453c82fatagen2026-09-24 13:07 UTC171
    }
31ce2453c82fatagen2026-09-24 13:07 UTC172
31ce2453c82fatagen2026-09-24 13:07 UTC173
    pub(crate) fn interactive_auth(challenge: InteractiveAuthChallenge) -> Self {
31ce2453c82fatagen2026-09-24 13:07 UTC174
        Self {
31ce2453c82fatagen2026-09-24 13:07 UTC175
            challenge: Some(Box::new(challenge)),
31ce2453c82fatagen2026-09-24 13:07 UTC176
            ..Self::new(
31ce2453c82fatagen2026-09-24 13:07 UTC177
                ErrorKind::InteractiveAuthRequired,
31ce2453c82fatagen2026-09-24 13:07 UTC178
                "interactive authentication is required",
31ce2453c82fatagen2026-09-24 13:07 UTC179
            )
96fdf90aacd6atagen2026-09-08 08:24 UTC180
        }
96fdf90aacd6atagen2026-09-08 08:24 UTC181
    }
96fdf90aacd6atagen2026-09-08 08:24 UTC182
96fdf90aacd6atagen2026-09-08 08:24 UTC183
    pub(crate) fn from_sdk(message: impl Into<String>, source: matrix_sdk::Error) -> Self {
96fdf90aacd6atagen2026-09-08 08:24 UTC184
        Self::with_source(classify_sdk_error(&source), message, source)
96fdf90aacd6atagen2026-09-08 08:24 UTC185
    }
96fdf90aacd6atagen2026-09-08 08:24 UTC186
96fdf90aacd6atagen2026-09-08 08:24 UTC187
    pub(crate) fn from_http(message: impl Into<String>, source: HttpError) -> Self {
96fdf90aacd6atagen2026-09-08 08:24 UTC188
        Self::with_source(classify_http_error(&source), message, source)
96fdf90aacd6atagen2026-09-08 08:24 UTC189
    }
31ce2453c82fatagen2026-09-24 13:07 UTC190
96fdf90aacd6atagen2026-09-08 08:24 UTC191
    pub(crate) fn from_refresh_token(
96fdf90aacd6atagen2026-09-08 08:24 UTC192
        message: impl Into<String>,
96fdf90aacd6atagen2026-09-08 08:24 UTC193
        source: RefreshTokenError,
96fdf90aacd6atagen2026-09-08 08:24 UTC194
    ) -> Self {
96fdf90aacd6atagen2026-09-08 08:24 UTC195
        Self::with_source(classify_refresh_token_error(&source), message, source)
96fdf90aacd6atagen2026-09-08 08:24 UTC196
    }
96fdf90aacd6atagen2026-09-08 08:24 UTC197
96fdf90aacd6atagen2026-09-08 08:24 UTC198
    pub(crate) fn from_recovery(message: impl Into<String>, source: RecoveryError) -> Self {
96fdf90aacd6atagen2026-09-08 08:24 UTC199
        let kind = match &source {
96fdf90aacd6atagen2026-09-08 08:24 UTC200
            RecoveryError::Sdk(source) => classify_sdk_error(source),
96fdf90aacd6atagen2026-09-08 08:24 UTC201
            RecoveryError::SecretStorage(SecretStorageError::Sdk(source)) => {
96fdf90aacd6atagen2026-09-08 08:24 UTC202
                classify_sdk_error(source)
96fdf90aacd6atagen2026-09-08 08:24 UTC203
            }
96fdf90aacd6atagen2026-09-08 08:24 UTC204
            RecoveryError::SecretStorage(SecretStorageError::ImportError { error, .. }) => {
96fdf90aacd6atagen2026-09-08 08:24 UTC205
                match error {
96fdf90aacd6atagen2026-09-08 08:24 UTC206
                    ImportError::Sdk(source) => classify_sdk_error(source),
31ce2453c82fatagen2026-09-24 13:07 UTC207
                    _ => ErrorKind::RecoveryRejected,
96fdf90aacd6atagen2026-09-08 08:24 UTC208
                }
96fdf90aacd6atagen2026-09-08 08:24 UTC209
            }
96fdf90aacd6atagen2026-09-08 08:24 UTC210
            RecoveryError::SecretStorage(SecretStorageError::Verification(source)) => {
96fdf90aacd6atagen2026-09-08 08:24 UTC211
                match source {
96fdf90aacd6atagen2026-09-08 08:24 UTC212
                    ManualVerifyError::Http(source) => classify_http_error(source),
31ce2453c82fatagen2026-09-24 13:07 UTC213
                    _ => ErrorKind::RecoveryRejected,
96fdf90aacd6atagen2026-09-08 08:24 UTC214
                }
96fdf90aacd6atagen2026-09-08 08:24 UTC215
            }
96fdf90aacd6atagen2026-09-08 08:24 UTC216
            RecoveryError::SecretStorage(SecretStorageError::SecretStorageKey(_)) => {
31ce2453c82fatagen2026-09-24 13:07 UTC217
                ErrorKind::RecoveryRejected
96fdf90aacd6atagen2026-09-08 08:24 UTC218
            }
31ce2453c82fatagen2026-09-24 13:07 UTC219
            RecoveryError::SecretStorage(SecretStorageError::Storage(_)) => ErrorKind::Store,
96fdf90aacd6atagen2026-09-08 08:24 UTC220
            RecoveryError::BackupExistsOnServer | RecoveryError::SecretStorage(_) => {
31ce2453c82fatagen2026-09-24 13:07 UTC221
                ErrorKind::RecoveryRejected
96fdf90aacd6atagen2026-09-08 08:24 UTC222
            }
96fdf90aacd6atagen2026-09-08 08:24 UTC223
        };
96fdf90aacd6atagen2026-09-08 08:24 UTC224
        Self::with_source(kind, message, source)
96fdf90aacd6atagen2026-09-08 08:24 UTC225
    }
96fdf90aacd6atagen2026-09-08 08:24 UTC226
96fdf90aacd6atagen2026-09-08 08:24 UTC227
    pub(crate) fn from_verification_request(
96fdf90aacd6atagen2026-09-08 08:24 UTC228
        message: impl Into<String>,
96fdf90aacd6atagen2026-09-08 08:24 UTC229
        source: RequestVerificationError,
96fdf90aacd6atagen2026-09-08 08:24 UTC230
    ) -> Self {
96fdf90aacd6atagen2026-09-08 08:24 UTC231
        let kind = match &source {
96fdf90aacd6atagen2026-09-08 08:24 UTC232
            RequestVerificationError::Sdk(source) => classify_sdk_error(source),
31ce2453c82fatagen2026-09-24 13:07 UTC233
            RequestVerificationError::RoomCreation(_) => ErrorKind::Encryption,
96fdf90aacd6atagen2026-09-08 08:24 UTC234
        };
96fdf90aacd6atagen2026-09-08 08:24 UTC235
        Self::with_source(kind, message, source)
96fdf90aacd6atagen2026-09-08 08:24 UTC236
    }
96fdf90aacd6atagen2026-09-08 08:24 UTC237
}
96fdf90aacd6atagen2026-09-08 08:24 UTC238
31ce2453c82fatagen2026-09-24 13:07 UTC239
impl PartialEq for Error {
31ce2453c82fatagen2026-09-24 13:07 UTC240
    fn eq(&self, other: &Self) -> bool {
31ce2453c82fatagen2026-09-24 13:07 UTC241
        self.kind == other.kind
31ce2453c82fatagen2026-09-24 13:07 UTC242
            && self.message == other.message
31ce2453c82fatagen2026-09-24 13:07 UTC243
            && self.challenge == other.challenge
9a25b6ce66f4atagen2026-10-08 11:15 UTC244
            && self.server == other.server
31ce2453c82fatagen2026-09-24 13:07 UTC245
    }
31ce2453c82fatagen2026-09-24 13:07 UTC246
}
31ce2453c82fatagen2026-09-24 13:07 UTC247
31ce2453c82fatagen2026-09-24 13:07 UTC248
pub(crate) fn classify_sdk_error(source: &matrix_sdk::Error) -> ErrorKind {
96fdf90aacd6atagen2026-09-08 08:24 UTC249
    match source {
96fdf90aacd6atagen2026-09-08 08:24 UTC250
        matrix_sdk::Error::Http(source) => classify_http_error(source),
96fdf90aacd6atagen2026-09-08 08:24 UTC251
        matrix_sdk::Error::OAuth(source) => classify_oauth_error(source),
31ce2453c82fatagen2026-09-24 13:07 UTC252
        matrix_sdk::Error::AuthenticationRequired => ErrorKind::Unauthenticated,
96fdf90aacd6atagen2026-09-08 08:24 UTC253
        matrix_sdk::Error::BadCryptoStoreState
96fdf90aacd6atagen2026-09-08 08:24 UTC254
        | matrix_sdk::Error::CryptoStoreError(_)
96fdf90aacd6atagen2026-09-08 08:24 UTC255
        | matrix_sdk::Error::CrossProcessLockError(_)
96fdf90aacd6atagen2026-09-08 08:24 UTC256
        | matrix_sdk::Error::StateStore(_)
96fdf90aacd6atagen2026-09-08 08:24 UTC257
        | matrix_sdk::Error::EventCacheStore(_)
31ce2453c82fatagen2026-09-24 13:07 UTC258
        | matrix_sdk::Error::MediaStore(_) => ErrorKind::Store,
96fdf90aacd6atagen2026-09-08 08:24 UTC259
        matrix_sdk::Error::NoOlmMachine
96fdf90aacd6atagen2026-09-08 08:24 UTC260
        | matrix_sdk::Error::OlmError(_)
96fdf90aacd6atagen2026-09-08 08:24 UTC261
        | matrix_sdk::Error::MegolmError(_)
31ce2453c82fatagen2026-09-24 13:07 UTC262
        | matrix_sdk::Error::DecryptorError(_) => ErrorKind::Encryption,
31ce2453c82fatagen2026-09-24 13:07 UTC263
        matrix_sdk::Error::Media(_) => ErrorKind::MediaUnavailable,
31ce2453c82fatagen2026-09-24 13:07 UTC264
        matrix_sdk::Error::Timeout => ErrorKind::Network,
31ce2453c82fatagen2026-09-24 13:07 UTC265
        _ => ErrorKind::Other,
96fdf90aacd6atagen2026-09-08 08:24 UTC266
    }
96fdf90aacd6atagen2026-09-08 08:24 UTC267
}
96fdf90aacd6atagen2026-09-08 08:24 UTC268
31ce2453c82fatagen2026-09-24 13:07 UTC269
fn classify_http_error(source: &HttpError) -> ErrorKind {
96fdf90aacd6atagen2026-09-08 08:24 UTC270
    match source {
31ce2453c82fatagen2026-09-24 13:07 UTC271
        HttpError::Reqwest(_) => ErrorKind::Network,
31ce2453c82fatagen2026-09-24 13:07 UTC272
        HttpError::Api(_) => ErrorKind::Server,
96fdf90aacd6atagen2026-09-08 08:24 UTC273
        HttpError::RefreshToken(source) => classify_refresh_token_error(source),
96fdf90aacd6atagen2026-09-08 08:24 UTC274
        HttpError::Cached(source) => classify_http_error(source),
31ce2453c82fatagen2026-09-24 13:07 UTC275
        _ => ErrorKind::Other,
96fdf90aacd6atagen2026-09-08 08:24 UTC276
    }
96fdf90aacd6atagen2026-09-08 08:24 UTC277
}
96fdf90aacd6atagen2026-09-08 08:24 UTC278
31ce2453c82fatagen2026-09-24 13:07 UTC279
fn classify_refresh_token_error(source: &RefreshTokenError) -> ErrorKind {
96fdf90aacd6atagen2026-09-08 08:24 UTC280
    match source {
31ce2453c82fatagen2026-09-24 13:07 UTC281
        RefreshTokenError::RefreshTokenRequired => ErrorKind::Unauthenticated,
96fdf90aacd6atagen2026-09-08 08:24 UTC282
        RefreshTokenError::MatrixAuth(source) => classify_http_error(source),
96fdf90aacd6atagen2026-09-08 08:24 UTC283
        RefreshTokenError::OAuth(source) => classify_oauth_error(source),
96fdf90aacd6atagen2026-09-08 08:24 UTC284
    }
96fdf90aacd6atagen2026-09-08 08:24 UTC285
}
96fdf90aacd6atagen2026-09-08 08:24 UTC286
31ce2453c82fatagen2026-09-24 13:07 UTC287
fn classify_oauth_error(source: &OAuthError) -> ErrorKind {
96fdf90aacd6atagen2026-09-08 08:24 UTC288
    let classify_token_request_error = |source: &_| match source {
31ce2453c82fatagen2026-09-24 13:07 UTC289
        RequestTokenError::Request(_) => ErrorKind::Network,
31ce2453c82fatagen2026-09-24 13:07 UTC290
        RequestTokenError::ServerResponse(_) => ErrorKind::Unauthenticated,
31ce2453c82fatagen2026-09-24 13:07 UTC291
        _ => ErrorKind::Other,
96fdf90aacd6atagen2026-09-08 08:24 UTC292
    };
96fdf90aacd6atagen2026-09-08 08:24 UTC293
    match source {
96fdf90aacd6atagen2026-09-08 08:24 UTC294
        OAuthError::Discovery(source) => match source {
96fdf90aacd6atagen2026-09-08 08:24 UTC295
            OAuthDiscoveryError::Http(source) => classify_http_error(source),
96fdf90aacd6atagen2026-09-08 08:24 UTC296
            OAuthDiscoveryError::Oidc(source) => classify_token_request_error(source),
31ce2453c82fatagen2026-09-24 13:07 UTC297
            _ => ErrorKind::Unauthenticated,
96fdf90aacd6atagen2026-09-08 08:24 UTC298
        },
96fdf90aacd6atagen2026-09-08 08:24 UTC299
        OAuthError::RefreshToken(source) => classify_token_request_error(source),
96fdf90aacd6atagen2026-09-08 08:24 UTC300
        OAuthError::AuthorizationCode(OAuthAuthorizationCodeError::RequestToken(source)) => {
96fdf90aacd6atagen2026-09-08 08:24 UTC301
            classify_token_request_error(source)
96fdf90aacd6atagen2026-09-08 08:24 UTC302
        }
31ce2453c82fatagen2026-09-24 13:07 UTC303
        OAuthError::AuthorizationCode(_) => ErrorKind::Unauthenticated,
96fdf90aacd6atagen2026-09-08 08:24 UTC304
        OAuthError::Logout(source) => match source {
31ce2453c82fatagen2026-09-24 13:07 UTC305
            OAuthTokenRevocationError::Revoke(RequestTokenError::Request(_)) => ErrorKind::Network,
96fdf90aacd6atagen2026-09-08 08:24 UTC306
            OAuthTokenRevocationError::Revoke(RequestTokenError::ServerResponse(_)) => {
31ce2453c82fatagen2026-09-24 13:07 UTC307
                ErrorKind::Unauthenticated
96fdf90aacd6atagen2026-09-08 08:24 UTC308
            }
31ce2453c82fatagen2026-09-24 13:07 UTC309
            _ => ErrorKind::Other,
96fdf90aacd6atagen2026-09-08 08:24 UTC310
        },
31ce2453c82fatagen2026-09-24 13:07 UTC311
        _ => ErrorKind::Unauthenticated,
96fdf90aacd6atagen2026-09-08 08:24 UTC312
    }
96fdf90aacd6atagen2026-09-08 08:24 UTC313
}