Skip to main content

velesdb_core/
error.rs

1//! Error types for `VelesDB`.
2//!
3//! This module provides a unified error type for all `VelesDB` operations,
4//! designed for professional API exposure to Python/Node clients.
5
6use thiserror::Error;
7
8/// Result type alias for `VelesDB` operations.
9pub type Result<T> = std::result::Result<T, Error>;
10
11/// Errors that can occur in `VelesDB` operations.
12///
13/// Each variant includes a descriptive error message suitable for end-users.
14/// Error codes follow the pattern `VELES-XXX` for easy debugging.
15#[derive(Error, Debug)]
16pub enum Error {
17    /// Collection already exists (VELES-001).
18    #[error("[VELES-001] Collection '{0}' already exists")]
19    CollectionExists(String),
20
21    /// Collection not found (VELES-002).
22    #[error("[VELES-002] Collection '{0}' not found")]
23    CollectionNotFound(String),
24
25    /// Point not found (VELES-003).
26    #[error("[VELES-003] Point with ID '{0}' not found")]
27    PointNotFound(u64),
28
29    /// Dimension mismatch (VELES-004).
30    #[error("[VELES-004] Vector dimension mismatch: expected {expected}, got {actual}")]
31    DimensionMismatch {
32        /// Expected dimension.
33        expected: usize,
34        /// Actual dimension.
35        actual: usize,
36    },
37
38    /// Invalid vector (VELES-005).
39    #[error("[VELES-005] Invalid vector: {0}")]
40    InvalidVector(String),
41
42    /// Storage error (VELES-006).
43    #[error("[VELES-006] Storage error: {0}")]
44    Storage(String),
45
46    /// Index error (VELES-007).
47    #[error("[VELES-007] Index error: {0}")]
48    Index(String),
49
50    /// Index corrupted (VELES-008).
51    ///
52    /// Indicates that index files are corrupted and need to be rebuilt.
53    #[error("[VELES-008] Index corrupted: {0}")]
54    IndexCorrupted(String),
55
56    /// Configuration error (VELES-009).
57    #[error("[VELES-009] Configuration error: {0}")]
58    Config(String),
59
60    /// Query parsing error (VELES-010).
61    ///
62    /// Wraps `VelesQL` parse errors with position and context information.
63    #[error("[VELES-010] Query error: {0}")]
64    Query(String),
65
66    /// IO error (VELES-011).
67    #[error("[VELES-011] IO error: {0}")]
68    Io(#[from] std::io::Error),
69
70    /// Serialization error (VELES-012).
71    #[error("[VELES-012] Serialization error: {0}")]
72    Serialization(String),
73
74    /// Internal error (VELES-013).
75    ///
76    /// Indicates an unexpected internal error. Please report if encountered.
77    #[error("[VELES-013] Internal error: {0}")]
78    Internal(String),
79
80    /// Vector not allowed on metadata-only collection (VELES-014).
81    #[error("[VELES-014] Vector not allowed on metadata-only collection '{0}'")]
82    VectorNotAllowed(String),
83
84    /// Search not supported on metadata-only collection (VELES-015).
85    #[error("[VELES-015] Vector search not supported on metadata-only collection '{0}'. Use query() instead.")]
86    SearchNotSupported(String),
87
88    /// Vector required for vector collection (VELES-016).
89    #[error("[VELES-016] Vector required for collection '{0}' (not metadata-only)")]
90    VectorRequired(String),
91
92    /// Schema validation error (VELES-017).
93    #[error("[VELES-017] Schema validation error: {0}")]
94    SchemaValidation(String),
95
96    /// Graph operation not supported (VELES-018).
97    #[error("[VELES-018] Graph operation not supported: {0}")]
98    GraphNotSupported(String),
99
100    /// Edge already exists (VELES-019).
101    #[error("[VELES-019] Edge with ID '{0}' already exists")]
102    EdgeExists(u64),
103
104    /// Edge not found (VELES-020).
105    #[error("[VELES-020] Edge with ID '{0}' not found")]
106    EdgeNotFound(u64),
107
108    /// Invalid edge label (VELES-021).
109    #[error("[VELES-021] Invalid edge label: {0}")]
110    InvalidEdgeLabel(String),
111
112    /// Node not found (VELES-022).
113    #[error("[VELES-022] Node with ID '{0}' not found")]
114    NodeNotFound(u64),
115
116    /// Numeric overflow (VELES-023).
117    ///
118    /// Indicates a numeric conversion would overflow or truncate.
119    /// Use `try_from()` instead of `as` casts for user-provided data.
120    #[error("[VELES-023] Numeric overflow: {0}")]
121    Overflow(String),
122
123    /// Column store error (VELES-024).
124    ///
125    /// Indicates a column store schema or primary key validation failure.
126    #[error("[VELES-024] Column store error: {0}")]
127    ColumnStoreError(String),
128
129    /// GPU operation error (VELES-025).
130    ///
131    /// Indicates a GPU parameter validation or operation failure.
132    #[error("[VELES-025] GPU error: {0}")]
133    GpuError(String),
134
135    /// Epoch mismatch (VELES-026).
136    ///
137    /// Indicates a stale mmap guard detected after a remap operation.
138    /// This is not recoverable — the guard must be re-acquired.
139    #[error("[VELES-026] Epoch mismatch: {0}")]
140    EpochMismatch(String),
141}
142
143impl Error {
144    /// Returns the error code (e.g., "VELES-001").
145    #[must_use]
146    pub const fn code(&self) -> &'static str {
147        match self {
148            Self::CollectionExists(_) => "VELES-001",
149            Self::CollectionNotFound(_) => "VELES-002",
150            Self::PointNotFound(_) => "VELES-003",
151            Self::DimensionMismatch { .. } => "VELES-004",
152            Self::InvalidVector(_) => "VELES-005",
153            Self::Storage(_) => "VELES-006",
154            Self::Index(_) => "VELES-007",
155            Self::IndexCorrupted(_) => "VELES-008",
156            Self::Config(_) => "VELES-009",
157            Self::Query(_) => "VELES-010",
158            Self::Io(_) => "VELES-011",
159            Self::Serialization(_) => "VELES-012",
160            Self::Internal(_) => "VELES-013",
161            Self::VectorNotAllowed(_) => "VELES-014",
162            Self::SearchNotSupported(_) => "VELES-015",
163            Self::VectorRequired(_) => "VELES-016",
164            Self::SchemaValidation(_) => "VELES-017",
165            Self::GraphNotSupported(_) => "VELES-018",
166            Self::EdgeExists(_) => "VELES-019",
167            Self::EdgeNotFound(_) => "VELES-020",
168            Self::InvalidEdgeLabel(_) => "VELES-021",
169            Self::NodeNotFound(_) => "VELES-022",
170            Self::Overflow(_) => "VELES-023",
171            Self::ColumnStoreError(_) => "VELES-024",
172            Self::GpuError(_) => "VELES-025",
173            Self::EpochMismatch(_) => "VELES-026",
174        }
175    }
176
177    /// Returns true if this error is recoverable.
178    ///
179    /// Non-recoverable errors include corruption and internal errors.
180    #[must_use]
181    pub const fn is_recoverable(&self) -> bool {
182        !matches!(
183            self,
184            Self::IndexCorrupted(_) | Self::Internal(_) | Self::EpochMismatch(_)
185        )
186    }
187}
188
189/// Conversion from `VelesQL` `ParseError`.
190impl From<crate::velesql::ParseError> for Error {
191    fn from(err: crate::velesql::ParseError) -> Self {
192        Self::Query(err.to_string())
193    }
194}