lumosai_vector_core/
error.rs

1//! Error types for the Lumos vector storage system
2
3use thiserror::Error;
4
5/// Result type alias for vector operations
6pub type Result<T> = std::result::Result<T, VectorError>;
7
8/// Comprehensive error type for vector storage operations
9#[derive(Error, Debug, Clone)]
10pub enum VectorError {
11    /// Index-related errors
12    #[error("Index '{0}' not found")]
13    IndexNotFound(String),
14    
15    #[error("Index '{0}' already exists")]
16    IndexAlreadyExists(String),
17    
18    #[error("Invalid index configuration: {0}")]
19    InvalidIndexConfig(String),
20    
21    /// Vector-related errors
22    #[error("Vector '{0}' not found")]
23    VectorNotFound(String),
24    
25    #[error("Dimension mismatch: expected {expected}, got {actual}")]
26    DimensionMismatch { expected: usize, actual: usize },
27    
28    #[error("Invalid vector data: {0}")]
29    InvalidVector(String),
30
31    #[error("Embedding generation failed: {0}")]
32    EmbeddingError(String),
33    
34    /// Query-related errors
35    #[error("Invalid query: {0}")]
36    InvalidQuery(String),
37    
38    #[error("Query timeout after {seconds} seconds")]
39    QueryTimeout { seconds: u64 },
40    
41    #[error("Invalid filter condition: {0}")]
42    InvalidFilter(String),
43    
44    /// Storage backend errors
45    #[error("Storage backend error: {0}")]
46    StorageBackend(String),
47    
48    #[error("Connection failed: {0}")]
49    ConnectionFailed(String),
50    
51    #[error("Authentication failed: {0}")]
52    AuthenticationFailed(String),
53    
54    #[error("Permission denied: {0}")]
55    PermissionDenied(String),
56    
57    /// Serialization errors
58    #[error("Serialization error: {0}")]
59    Serialization(String),
60    
61    #[error("Deserialization error: {0}")]
62    Deserialization(String),
63    
64    /// Configuration errors
65    #[error("Invalid configuration: {0}")]
66    InvalidConfig(String),
67    
68    #[error("Missing required configuration: {0}")]
69    MissingConfig(String),
70    
71    /// Resource errors
72    #[error("Resource limit exceeded: {0}")]
73    ResourceLimitExceeded(String),
74    
75    #[error("Insufficient storage space")]
76    InsufficientStorage,
77    
78    #[error("Memory allocation failed")]
79    OutOfMemory,
80    
81    /// Operation errors
82    #[error("Operation not supported: {0}")]
83    NotSupported(String),
84    
85    #[error("Operation failed: {0}")]
86    OperationFailed(String),
87    
88    #[error("Concurrent modification detected")]
89    ConcurrentModification,
90    
91    /// Internal errors
92    #[error("Internal error: {0}")]
93    Internal(String),
94    
95    #[error("Unexpected error: {0}")]
96    Unexpected(String),
97}
98
99impl VectorError {
100    /// Create an index not found error
101    pub fn index_not_found(name: impl Into<String>) -> Self {
102        Self::IndexNotFound(name.into())
103    }
104    
105    /// Create an index already exists error
106    pub fn index_already_exists(name: impl Into<String>) -> Self {
107        Self::IndexAlreadyExists(name.into())
108    }
109    
110    /// Create a dimension mismatch error
111    pub fn dimension_mismatch(expected: usize, actual: usize) -> Self {
112        Self::DimensionMismatch { expected, actual }
113    }
114    
115    /// Create a vector not found error
116    pub fn vector_not_found(id: impl Into<String>) -> Self {
117        Self::VectorNotFound(id.into())
118    }
119    
120    /// Create a storage backend error
121    pub fn storage_backend(msg: impl Into<String>) -> Self {
122        Self::StorageBackend(msg.into())
123    }
124    
125    /// Create a connection failed error
126    pub fn connection_failed(msg: impl Into<String>) -> Self {
127        Self::ConnectionFailed(msg.into())
128    }
129    
130    /// Create an invalid configuration error
131    pub fn invalid_config(msg: impl Into<String>) -> Self {
132        Self::InvalidConfig(msg.into())
133    }
134    
135    /// Create a serialization error
136    pub fn serialization(msg: impl Into<String>) -> Self {
137        Self::Serialization(msg.into())
138    }
139    
140    /// Create an internal error
141    pub fn internal(msg: impl Into<String>) -> Self {
142        Self::Internal(msg.into())
143    }
144
145    /// Create an embedding error
146    pub fn embedding_error(msg: impl Into<String>) -> Self {
147        Self::EmbeddingError(msg.into())
148    }
149    
150    /// Check if this error is retryable
151    pub fn is_retryable(&self) -> bool {
152        matches!(
153            self,
154            VectorError::QueryTimeout { .. }
155                | VectorError::ConnectionFailed(_)
156                | VectorError::InsufficientStorage
157                | VectorError::ConcurrentModification
158        )
159    }
160    
161    /// Check if this error is a client error (4xx equivalent)
162    pub fn is_client_error(&self) -> bool {
163        matches!(
164            self,
165            VectorError::IndexNotFound(_)
166                | VectorError::VectorNotFound(_)
167                | VectorError::DimensionMismatch { .. }
168                | VectorError::InvalidQuery(_)
169                | VectorError::InvalidFilter(_)
170                | VectorError::InvalidVector(_)
171                | VectorError::InvalidConfig(_)
172                | VectorError::MissingConfig(_)
173                | VectorError::NotSupported(_)
174        )
175    }
176    
177    /// Check if this error is a server error (5xx equivalent)
178    pub fn is_server_error(&self) -> bool {
179        matches!(
180            self,
181            VectorError::StorageBackend(_)
182                | VectorError::Internal(_)
183                | VectorError::Unexpected(_)
184                | VectorError::OutOfMemory
185                | VectorError::OperationFailed(_)
186        )
187    }
188}
189
190/// Convert from standard I/O errors
191impl From<std::io::Error> for VectorError {
192    fn from(err: std::io::Error) -> Self {
193        VectorError::StorageBackend(err.to_string())
194    }
195}
196
197/// Convert from serde JSON errors
198#[cfg(feature = "serde")]
199impl From<serde_json::Error> for VectorError {
200    fn from(err: serde_json::Error) -> Self {
201        VectorError::Serialization(err.to_string())
202    }
203}
204
205#[cfg(test)]
206mod tests {
207    use super::*;
208    
209    #[test]
210    fn test_error_creation() {
211        let err = VectorError::index_not_found("test_index");
212        assert!(matches!(err, VectorError::IndexNotFound(_)));
213        assert!(err.is_client_error());
214        assert!(!err.is_retryable());
215    }
216    
217    #[test]
218    fn test_dimension_mismatch() {
219        let err = VectorError::dimension_mismatch(384, 512);
220        assert!(matches!(err, VectorError::DimensionMismatch { expected: 384, actual: 512 }));
221    }
222    
223    #[test]
224    fn test_error_classification() {
225        assert!(VectorError::QueryTimeout { seconds: 30 }.is_retryable());
226        assert!(VectorError::InvalidQuery("bad query".to_string()).is_client_error());
227        assert!(VectorError::Internal("system error".to_string()).is_server_error());
228    }
229}