core_crypto/error/
mod.rs

1mod keystore;
2mod leaf;
3mod mls;
4mod proteus;
5mod recursive;
6mod wrapper;
7
8pub use keystore::KeystoreError;
9pub use leaf::LeafError;
10pub use mls::{MlsError, MlsErrorKind};
11pub use proteus::{ProteusError, ProteusErrorKind};
12pub use recursive::{RecursiveError, ToRecursiveError};
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    /// Invalid [crate::transaction_context::TransactionContext]. This context has been finished and can no longer be
21    /// used.
22    #[cfg_attr(
23        target_family = "wasm",
24        error(
25            "This transaction context has already been finished. You most likely used the context outside the callback
26            or you forget to `await` a Promise inside the transaction callback."
27        )
28    )]
29    #[cfg_attr(
30        not(target_family = "wasm"),
31        error("This transaction context has already been finished and can no longer be used.")
32    )]
33    InvalidTransactionContext,
34    /// The proteus client has been called but has not been initialized yet
35    #[error("Proteus client hasn't been initialized")]
36    ProteusNotInitialized,
37    /// Mls Transport Callbacks were not provided
38    #[error("The mls transport callbacks needed for CoreCrypto to operate were not set")]
39    MlsTransportNotProvided,
40    /// Any error that occurs during mls transport.
41    #[error("Error during mls transport: {0}")]
42    ErrorDuringMlsTransport(String),
43    /// This item requires a feature that the core-crypto library was built without
44    #[error("This item requires a feature that the core-crypto library was built without: {0}")]
45    FeatureDisabled(&'static str),
46    /// A key store operation failed
47    #[error(transparent)]
48    Keystore(#[from] KeystoreError),
49    /// Invalid history secret
50    #[error("Invalid history secret: {0}")]
51    InvalidHistorySecret(&'static str),
52    /// An external MLS operation failed
53    #[error(transparent)]
54    Mls(#[from] MlsError),
55    /// E2EI error
56    #[error(transparent)]
57    E2eIdentity(#[from] wire_e2e_identity::E2eIdentityError),
58    /// A Proteus operation failed
59    #[error(transparent)]
60    Proteus(#[from] ProteusError),
61    /// A crate-internal operation failed
62    #[error(transparent)]
63    Recursive(#[from] RecursiveError),
64}
65
66/// Produce the error message from the innermost wrapped error.
67///
68/// We produce arbitrarily nested errors which are very helpful
69/// at capturing relevant context, and very bad at surfacing the
70/// root error cause in a default `.to_string()` call.
71///
72/// This trait, automatically implemented for all standard errors,
73/// rectifies this problem.
74pub trait InnermostErrorMessage {
75    /// Produce the error message from the innermost wrapped error.
76    fn innermost_error_message(&self) -> String;
77}
78
79impl<E: std::error::Error> InnermostErrorMessage for E {
80    fn innermost_error_message(&self) -> String {
81        let mut err: &dyn std::error::Error = self;
82        while let Some(source) = err.source() {
83            err = source;
84        }
85        err.to_string()
86    }
87}
88
89#[cfg(test)]
90mod tests {
91    use super::*;
92
93    #[test]
94    fn can_unpack_wrapped_error() {
95        let inner = Error::InvalidTransactionContext;
96        let outer = RecursiveError::root("wrapping the inner for test purposes")(inner);
97        let message = outer.innermost_error_message();
98        assert_eq!(message, Error::InvalidTransactionContext.to_string());
99    }
100}