Skip to main content

reddb_engine/storage/
error.rs

1//! Canonical storage errors shared by native and browser hosts.
2use super::entity::EntityId;
3#[cfg(feature = "full")]
4use super::segment::SegmentError;
5use std::fmt;
6
7#[derive(Debug, Clone, PartialEq, Eq)]
8pub struct StorageIntegrityError {
9    pub zone: String,
10    pub id: String,
11    pub collection: Option<String>,
12    pub detail: String,
13}
14
15impl StorageIntegrityError {
16    pub fn new(
17        zone: impl Into<String>,
18        id: impl Into<String>,
19        collection: Option<String>,
20        detail: impl Into<String>,
21    ) -> Self {
22        Self {
23            zone: zone.into(),
24            id: id.into(),
25            collection,
26            detail: detail.into(),
27        }
28    }
29}
30
31impl fmt::Display for StorageIntegrityError {
32    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
33        write!(
34            f,
35            "storage integrity failure: zone={} id={}",
36            self.zone, self.id
37        )?;
38        if let Some(collection) = &self.collection {
39            write!(f, " collection={collection}")?;
40        }
41        write!(
42            f,
43            ": {}. RedDB refused to serve unverified bytes. Preserve the database and its recovery files; restore from a verified backup or consult the recovery documentation for this storage format.",
44            self.detail
45        )
46    }
47}
48
49/// Errors from UnifiedStore operations
50#[derive(Debug)]
51pub enum StoreError {
52    /// Collection already exists
53    CollectionExists(String),
54    /// Collection not found
55    CollectionNotFound(String),
56    /// Entity not found
57    EntityNotFound(EntityId),
58    /// Too many cross-references
59    TooManyRefs(EntityId),
60    /// Segment error
61    #[cfg(feature = "full")]
62    Segment(SegmentError),
63    /// I/O error
64    Io(std::io::Error),
65    /// Checksummed storage bytes failed validation.
66    StorageIntegrity(StorageIntegrityError),
67    /// Serialization error
68    Serialization(String),
69    /// A read must be rejected before allocating beyond its allowance.
70    ReadLimitExceeded {
71        required_bytes: usize,
72        limit_bytes: usize,
73    },
74    /// Internal error (lock poisoning, invariant violation)
75    Internal(String),
76}
77
78impl std::fmt::Display for StoreError {
79    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
80        match self {
81            Self::CollectionExists(name) => write!(f, "Collection already exists: {}", name),
82            Self::CollectionNotFound(name) => write!(f, "Collection not found: {}", name),
83            Self::EntityNotFound(id) => write!(f, "Entity not found: {}", id),
84            Self::TooManyRefs(id) => write!(f, "Too many cross-references for entity: {}", id),
85            #[cfg(feature = "full")]
86            Self::Segment(e) => write!(f, "Segment error: {:?}", e),
87            Self::Io(e) => write!(f, "I/O error: {}", e),
88            Self::StorageIntegrity(e) => write!(f, "{e}"),
89            Self::Serialization(msg) => write!(f, "Serialization error: {}", msg),
90            Self::ReadLimitExceeded {
91                required_bytes,
92                limit_bytes,
93            } => write!(
94                f,
95                "read needs {required_bytes} bytes over read memory limit {limit_bytes}"
96            ),
97            Self::Internal(msg) => write!(f, "Internal error: {}", msg),
98        }
99    }
100}
101
102impl std::error::Error for StoreError {}
103
104#[cfg(feature = "full")]
105impl From<SegmentError> for StoreError {
106    fn from(e: SegmentError) -> Self {
107        Self::Segment(e)
108    }
109}
110
111impl From<std::io::Error> for StoreError {
112    fn from(e: std::io::Error) -> Self {
113        Self::Io(e)
114    }
115}