Skip to main content

eventbus_core/
error.rs

1use thiserror::Error;
2
3/// Errors returned by the event bus.
4///
5/// The enum is marked `#[non_exhaustive]` so new variants can be added in a
6/// non-breaking way; external crates must include a `_ => ...` arm when
7/// matching exhaustively.
8///
9/// Prefer [`EventBusError::source`] when wrapping an underlying error from a
10/// backend or codec — it preserves the causal chain via [`std::error::Error::source`],
11/// allowing tracing/observability stacks to render the full chain without
12/// losing typed information to stringification.
13#[derive(Debug, Error)]
14#[non_exhaustive]
15pub enum EventBusError {
16    #[error("internal error: {0}")]
17    Internal(String),
18
19    #[error("validation error: {0}")]
20    Validation(String),
21
22    #[error("serialization error: {0}")]
23    Serialization(String),
24
25    #[error("invalid state transition: {from} -> {to}")]
26    InvalidTransition { from: String, to: String },
27
28    #[error("connection error: {0}")]
29    Connection(String),
30
31    #[error("timeout: {0}")]
32    Timeout(String),
33
34    /// An underlying error from a backend, codec, or dependency, with its
35    /// source chain preserved. Construct via [`EventBusError::source`].
36    #[error("{context}")]
37    Source {
38        context: String,
39        #[source]
40        source: Box<dyn std::error::Error + Send + Sync + 'static>,
41    },
42}
43
44impl EventBusError {
45    /// Wrap an underlying error with a human-readable context string while
46    /// preserving the source chain for `error.source()` traversal.
47    ///
48    /// # Example
49    ///
50    /// ```no_run
51    /// use eventbus_core::EventBusError;
52    ///
53    /// fn parse_int(s: &str) -> Result<u32, EventBusError> {
54    ///     s.parse::<u32>()
55    ///         .map_err(|e| EventBusError::source("parsing retry attempt", e))
56    /// }
57    /// ```
58    pub fn source<E>(context: impl Into<String>, err: E) -> Self
59    where
60        E: std::error::Error + Send + Sync + 'static,
61    {
62        Self::Source {
63            context: context.into(),
64            source: Box::new(err),
65        }
66    }
67}