Skip to main content

snowflake_gen/
error.rs

1use std::error::Error;
2use std::fmt;
3
4/// All errors that the snowflake crate can produce.
5#[derive(Debug, Clone, PartialEq, Eq)]
6pub enum SnowflakeError {
7    /// The bit widths of all four fields do not sum to 63.
8    ///
9    /// An `i64` has one sign bit, so the remaining 63 bits must be fully
10    /// allocated to avoid negative IDs or wasted space.
11    InvalidBitLayout {
12        t: u8,
13        m: u8,
14        n: u8,
15        s: u8,
16        total: u8,
17    },
18
19    /// A `machine_id` was provided that exceeds the layout's maximum.
20    MachineIdOutOfRange { given: i64, max: i64 },
21
22    /// A `node_id` was provided that exceeds the layout's maximum.
23    NodeIdOutOfRange { given: i64, max: i64 },
24
25    /// The global generator has already been initialized.
26    ///
27    /// [`init`](crate::init) / [`init_with_epoch`](crate::init_with_epoch) can
28    /// only be called once per process.  Re-initialization is rejected because
29    /// existing thread-local generators would keep using the old configuration,
30    /// leading to inconsistent ID layouts.  To change the configuration, restart
31    /// the process so that all thread-local state is cleared.
32    AlreadyInitialized,
33
34    /// More threads have called [`next_id`](crate::next_id) than the layout's
35    /// `node_id_bits` can accommodate.
36    ///
37    /// With the default 5 `node_id_bits`, at most 32 threads (node IDs 0..=31)
38    /// can generate IDs.  If your application needs more threads, increase
39    /// `node_id_bits` (and reduce `machine_id_bits` or `timestamp_bits` to
40    /// compensate) when calling [`init`](crate::init).
41    NodeIdExhausted { max: i64 },
42
43    /// The system clock moved backwards, which would break ID monotonicity.
44    ClockMovedBackwards,
45
46    /// The system clock is not available (e.g. time before epoch).
47    ClockBeforeEpoch,
48}
49
50impl fmt::Display for SnowflakeError {
51    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
52        match self {
53            Self::InvalidBitLayout { t, m, n, s, total } => write!(
54                f,
55                "bit fields must sum to exactly 63, \
56                 got timestamp({t}) + machine_id({m}) + node_id({n}) + sequence({s}) = {total}"
57            ),
58            Self::MachineIdOutOfRange { given, max } => write!(
59                f,
60                "machine_id {given} exceeds maximum {max} for the configured bit width"
61            ),
62            Self::NodeIdOutOfRange { given, max } => write!(
63                f,
64                "node_id {given} exceeds maximum {max} for the configured bit width"
65            ),
66            Self::AlreadyInitialized => f.write_str(
67                "global snowflake generator is already initialized; restart the process to reconfigure",
68            ),
69            Self::NodeIdExhausted { max } => write!(
70                f,
71                "thread count exceeded the maximum node_id ({max}); \
72                 increase node_id_bits in your BitLayout to support more threads"
73            ),
74            Self::ClockMovedBackwards => {
75                f.write_str("system clock moved backwards; cannot guarantee monotonic IDs")
76            }
77            Self::ClockBeforeEpoch => {
78                f.write_str("system clock error: time is before the configured epoch")
79            }
80        }
81    }
82}
83
84impl Error for SnowflakeError {}