Skip to main content

core_crypto/error/
mod.rs

1mod keystore;
2mod open_mls;
3mod proteus;
4mod recursive;
5mod tls;
6mod wrapper;
7
8pub use keystore::KeystoreError;
9pub use open_mls::{OpenMlsError, OpenMlsErrorKind};
10pub use proteus::{ProteusError, ProteusErrorKind};
11pub use recursive::{RecursiveError, ToRecursiveError};
12pub use tls::TlsCodecError;
13
14/// A module-specific [Result][core::result::Result] type with a default error variant.
15pub type Result<T, E = Error> = core::result::Result<T, E>;
16
17/// Errors produced by the root module group
18#[derive(Debug, thiserror::Error)]
19pub enum Error {
20    /// The proteus client has been called but has not been initialized yet
21    #[error("Proteus client hasn't been initialized")]
22    ProteusNotInitialized,
23    /// Mls Transport Callbacks were not provided
24    #[error("The mls transport callbacks needed for CoreCrypto to operate were not set")]
25    MlsTransportNotProvided,
26    /// Any error that occurs during mls transport.
27    #[error("Error during mls transport: {0}")]
28    ErrorDuringMlsTransport(String),
29    /// This item requires a feature that the core-crypto library was built without
30    #[error("This item requires a feature that the core-crypto library was built without: {0}")]
31    FeatureDisabled(&'static str),
32    /// A key store operation failed
33    #[error(transparent)]
34    Keystore(#[from] KeystoreError),
35    /// Invalid history secret
36    #[error("Invalid history secret: {0}")]
37    InvalidHistorySecret(&'static str),
38    /// An external MLS operation failed
39    #[error(transparent)]
40    OpenMls(#[from] OpenMlsError),
41    /// E2EI error
42    #[error(transparent)]
43    E2eIdentity(#[from] wire_e2e_identity::E2eIdentityError),
44    /// A Proteus operation failed
45    #[error(transparent)]
46    Proteus(#[from] ProteusError),
47    /// A crate-internal operation failed
48    #[error(transparent)]
49    Recursive(#[from] RecursiveError),
50}
51
52/// Produce the error message from the innermost wrapped error.
53///
54/// We produce arbitrarily nested errors which are very helpful
55/// at capturing relevant context, and very bad at surfacing the
56/// root error cause in a default `.to_string()` call.
57///
58/// This trait, automatically implemented for all standard errors,
59/// rectifies this problem.
60pub trait InnermostErrorMessage {
61    /// Produce the error message from the innermost wrapped error.
62    fn innermost_error_message(&self) -> String;
63}
64
65impl<E: std::error::Error> InnermostErrorMessage for E {
66    fn innermost_error_message(&self) -> String {
67        let mut err: &dyn std::error::Error = self;
68        while let Some(source) = err.source() {
69            err = source;
70        }
71        err.to_string()
72    }
73}
74
75#[cfg(test)]
76mod tests {
77    use super::*;
78
79    #[test]
80    fn can_unpack_wrapped_error() {
81        let inner = Error::MlsTransportNotProvided;
82        let outer = RecursiveError::context("wrapping the inner for test purposes")(inner);
83        let message = outer.innermost_error_message();
84        assert_eq!(message, Error::MlsTransportNotProvided.to_string());
85    }
86}