Skip to main content

manifoldb_graph/store/
error.rs

1//! Error types for graph storage operations.
2
3use manifoldb_core::{CoreError, EdgeId, EntityId};
4use manifoldb_storage::StorageError;
5use thiserror::Error;
6
7/// Errors that can occur in graph storage operations.
8#[derive(Debug, Error)]
9pub enum GraphError {
10    /// An entity (node) was not found.
11    #[error("entity not found: {0}")]
12    EntityNotFound(EntityId),
13
14    /// An edge was not found.
15    #[error("edge not found: {0}")]
16    EdgeNotFound(EdgeId),
17
18    /// Referenced entity does not exist when creating an edge.
19    #[error("referenced entity does not exist: {0}")]
20    InvalidEntityReference(EntityId),
21
22    /// An entity with the given ID already exists.
23    #[error("entity already exists: {0}")]
24    EntityAlreadyExists(EntityId),
25
26    /// An edge with the given ID already exists.
27    #[error("edge already exists: {0}")]
28    EdgeAlreadyExists(EdgeId),
29
30    /// An encoding or decoding error occurred.
31    #[error("encoding error: {0}")]
32    Encoding(String),
33
34    /// A storage backend error occurred.
35    #[error("storage error: {0}")]
36    Storage(#[from] StorageError),
37
38    /// An internal error occurred.
39    #[error("internal error: {0}")]
40    Internal(String),
41
42    /// An invalid edge weight was encountered.
43    #[error("invalid edge weight on edge {edge_id}: {message}")]
44    InvalidWeight {
45        /// The edge with the invalid weight.
46        edge_id: EdgeId,
47        /// Description of the weight issue.
48        message: String,
49    },
50
51    /// Data corruption detected in storage.
52    #[error("data corruption: {0}")]
53    DataCorruption(String),
54
55    /// Graph is too large for the requested operation.
56    #[error("graph too large: {node_count} nodes exceeds limit of {limit}")]
57    GraphTooLarge {
58        /// The number of nodes in the graph.
59        node_count: usize,
60        /// The configured limit.
61        limit: usize,
62    },
63}
64
65impl From<CoreError> for GraphError {
66    fn from(err: CoreError) -> Self {
67        match err {
68            CoreError::Encoding(msg) => Self::Encoding(msg),
69            CoreError::TypeMismatch { expected, actual, value } => {
70                let value_info = value.map(|v| format!(" (value: {v})")).unwrap_or_default();
71                Self::Encoding(format!(
72                    "type mismatch: expected {expected}, got {actual}{value_info}"
73                ))
74            }
75            CoreError::Validation(msg) => Self::Internal(msg),
76        }
77    }
78}
79
80/// Result type for graph operations.
81pub type GraphResult<T> = Result<T, GraphError>;
82
83#[cfg(test)]
84mod tests {
85    use super::*;
86
87    #[test]
88    fn error_display() {
89        let err = GraphError::EntityNotFound(EntityId::new(42));
90        assert!(err.to_string().contains("42"));
91
92        let err = GraphError::EdgeNotFound(EdgeId::new(123));
93        assert!(err.to_string().contains("123"));
94    }
95
96    #[test]
97    fn from_core_error() {
98        let core_err = CoreError::Encoding("test error".to_owned());
99        let graph_err: GraphError = core_err.into();
100        assert!(matches!(graph_err, GraphError::Encoding(_)));
101    }
102}