Skip to main content

edgestore/
error.rs

1use std::fmt;
2
3/// All error variants returned by EdgeStore operations.
4#[derive(Debug)]
5pub enum EdgestoreError {
6    /// Underlying I/O error.
7    Io(std::io::Error),
8    /// CRC32C checksum mismatch.
9    Checksum {
10        /// Expected CRC32C value.
11        expected: u32,
12        /// Computed CRC32C value.
13        got: u32,
14    },
15    /// Corrupt WAL record.
16    CorruptRecord(String),
17    /// Corrupt namespace-key encoding.
18    CorruptKey,
19    /// WAL rotation threshold reached.
20    WalFull,
21    /// Another writer holds the database lock.
22    WriterBusy,
23    /// Invalid operation (e.g. transaction not active).
24    InvalidOperation(String),
25    /// Namespace length exceeds u16::MAX bytes.
26    NamespaceTooLong {
27        /// Actual namespace length.
28        len: usize,
29        /// Maximum allowed namespace length.
30        max: usize,
31    },
32    /// Key not found (used by storage backends).
33    KeyNotFound,
34    /// WAL or segment format version mismatch.
35    FormatVersion {
36        /// Expected format version.
37        expected: u8,
38        /// Actual format version found in file.
39        got: u8,
40    },
41    /// Corrupt segment file.
42    SegmentCorrupt(String),
43    /// Corrupt manifest file.
44    ManifestCorrupt(String),
45    /// Compaction failed.
46    CompactionError(String),
47    /// Replication sync failed.
48    ReplicationError(String),
49    /// Vector dimension mismatch.
50    DimensionMismatch {
51        /// Expected byte count (dims * element_size).
52        expected: usize,
53        /// Actual byte count provided.
54        actual: usize,
55    },
56    /// General corrupt data error.
57    CorruptData(String),
58}
59
60impl fmt::Display for EdgestoreError {
61    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
62        match self {
63            EdgestoreError::Io(e) => write!(f, "I/O error: {}", e),
64            EdgestoreError::Checksum { expected, got } => {
65                write!(f, "CRC32C mismatch: expected {:#010x}, got {:#010x}", expected, got)
66            }
67            EdgestoreError::CorruptRecord(msg) => write!(f, "corrupt WAL record: {}", msg),
68            EdgestoreError::CorruptKey => write!(f, "corrupt key encoding"),
69            EdgestoreError::WalFull => write!(f, "WAL rotation threshold reached"),
70            EdgestoreError::WriterBusy => write!(f, "another writer holds the database lock"),
71            EdgestoreError::InvalidOperation(msg) => write!(f, "invalid operation: {}", msg),
72            EdgestoreError::NamespaceTooLong { len, max } => {
73                write!(f, "namespace length {} exceeds maximum {}", len, max)
74            }
75            EdgestoreError::KeyNotFound => write!(f, "key not found"),
76            EdgestoreError::FormatVersion { expected, got } => {
77                write!(f, "WAL format version mismatch: expected {}, got {}", expected, got)
78            }
79            EdgestoreError::SegmentCorrupt(msg) => write!(f, "segment corrupt: {}", msg),
80            EdgestoreError::ManifestCorrupt(msg) => write!(f, "manifest corrupt: {}", msg),
81            EdgestoreError::CompactionError(msg) => write!(f, "compaction error: {}", msg),
82            EdgestoreError::ReplicationError(msg) => write!(f, "replication error: {}", msg),
83            EdgestoreError::DimensionMismatch { expected, actual } => {
84                write!(f, "dimension mismatch: expected {} bytes, got {}", expected, actual)
85            }
86            EdgestoreError::CorruptData(msg) => write!(f, "corrupt data: {}", msg),
87        }
88    }
89}
90
91impl std::error::Error for EdgestoreError {}
92
93impl From<std::io::Error> for EdgestoreError {
94    fn from(e: std::io::Error) -> Self {
95        EdgestoreError::Io(e)
96    }
97}
98
99#[cfg(test)]
100mod tests {
101    use super::*;
102
103    #[test]
104    fn test_display_variants() {
105        let cases: &[(&str, EdgestoreError)] = &[
106            ("corrupt WAL record: bad data", EdgestoreError::CorruptRecord("bad data".to_string())),
107            ("corrupt key encoding", EdgestoreError::CorruptKey),
108            ("WAL rotation threshold reached", EdgestoreError::WalFull),
109            ("another writer holds the database lock", EdgestoreError::WriterBusy),
110            ("invalid operation: not active", EdgestoreError::InvalidOperation("not active".to_string())),
111            ("namespace length 70000 exceeds maximum 65535", EdgestoreError::NamespaceTooLong { len: 70000, max: 65535 }),
112            ("key not found", EdgestoreError::KeyNotFound),
113            ("WAL format version mismatch: expected 1, got 2", EdgestoreError::FormatVersion { expected: 1, got: 2 }),
114            ("segment corrupt: bad block", EdgestoreError::SegmentCorrupt("bad block".to_string())),
115            ("manifest corrupt: truncated", EdgestoreError::ManifestCorrupt("truncated".to_string())),
116            ("compaction error: oops", EdgestoreError::CompactionError("oops".to_string())),
117        ];
118
119        for (expected, err) in cases {
120            assert_eq!(format!("{}", err), *expected, "Display mismatch for {:?}", err);
121        }
122    }
123
124    #[test]
125    fn test_io_from_conversion() {
126        let io_err = std::io::Error::new(std::io::ErrorKind::NotFound, "file gone");
127        let edge_err = EdgestoreError::from(io_err);
128        assert!(matches!(edge_err, EdgestoreError::Io(_)));
129    }
130}