1use thiserror::Error;
7
8pub type Result<T> = std::result::Result<T, Error>;
10
11#[derive(Error, Debug)]
16#[non_exhaustive]
17pub enum Error {
18 #[error("[VELES-001] Collection '{0}' already exists")]
20 CollectionExists(String),
21
22 #[error("[VELES-002] Collection '{0}' not found")]
24 CollectionNotFound(String),
25
26 #[error("[VELES-003] Point with ID '{0}' not found")]
28 PointNotFound(u64),
29
30 #[error("[VELES-004] Vector dimension mismatch: expected {expected}, got {actual}")]
32 DimensionMismatch {
33 expected: usize,
35 actual: usize,
37 },
38
39 #[error("[VELES-005] Invalid vector: {0}")]
41 InvalidVector(String),
42
43 #[error("[VELES-006] Storage error: {0}")]
45 Storage(String),
46
47 #[error("[VELES-007] Index error: {0}")]
49 Index(String),
50
51 #[error("[VELES-008] Index corrupted: {0}")]
55 IndexCorrupted(String),
56
57 #[error("[VELES-009] Configuration error: {0}")]
59 Config(String),
60
61 #[error("[VELES-010] Query error: {0}")]
65 Query(String),
66
67 #[error("[VELES-011] IO error: {0}")]
69 Io(#[from] std::io::Error),
70
71 #[error("[VELES-012] Serialization error: {0}")]
73 Serialization(String),
74
75 #[error("[VELES-013] Internal error: {0}")]
79 Internal(String),
80
81 #[error("[VELES-014] Vector not allowed on metadata-only collection '{0}'")]
83 VectorNotAllowed(String),
84
85 #[error("[VELES-015] Vector search not supported on metadata-only collection '{0}'. Use query() instead.")]
87 SearchNotSupported(String),
88
89 #[error("[VELES-016] Vector required for collection '{0}' (not metadata-only)")]
91 VectorRequired(String),
92
93 #[error("[VELES-017] Schema validation error: {0}")]
95 SchemaValidation(String),
96
97 #[error("[VELES-018] Graph operation not supported: {0}")]
99 GraphNotSupported(String),
100
101 #[error("[VELES-019] Edge with ID '{0}' already exists")]
103 EdgeExists(u64),
104
105 #[error("[VELES-020] Edge with ID '{0}' not found")]
107 EdgeNotFound(u64),
108
109 #[error("[VELES-021] Invalid edge label: {0}")]
111 InvalidEdgeLabel(String),
112
113 #[error("[VELES-022] Node with ID '{0}' not found")]
115 NodeNotFound(u64),
116
117 #[error("[VELES-023] Numeric overflow: {0}")]
122 Overflow(String),
123
124 #[error("[VELES-024] Column store error: {0}")]
128 ColumnStoreError(String),
129
130 #[error("[VELES-025] GPU error: {0}")]
134 GpuError(String),
135
136 #[error("[VELES-026] Epoch mismatch: {0}")]
141 EpochMismatch(String),
142
143 #[error("[VELES-027] Guard-rail violation: {0}")]
148 GuardRail(String),
149
150 #[error("[VELES-028] Invalid quantizer config: {0}")]
155 InvalidQuantizerConfig(String),
156
157 #[error("[VELES-029] Training failed: {0}")]
162 TrainingFailed(String),
163
164 #[error("[VELES-030] Sparse index error: {0}")]
166 SparseIndexError(String),
167
168 #[error("[VELES-031] Database is already opened by another process: {0}")]
170 DatabaseLocked(String),
171
172 #[error("[VELES-032] Invalid dimension {dimension}: must be between {min} and {max}")]
176 InvalidDimension {
177 dimension: usize,
179 min: usize,
181 max: usize,
183 },
184
185 #[error("[VELES-033] Allocation failed: {0}")]
189 AllocationFailed(String),
190
191 #[error("[VELES-034] Invalid collection name '{name}': {reason}")]
196 InvalidCollectionName {
197 name: String,
199 reason: String,
201 },
202}
203
204impl Error {
205 #[must_use]
207 pub const fn code(&self) -> &'static str {
208 match self {
209 Self::CollectionExists(_) => "VELES-001",
210 Self::CollectionNotFound(_) => "VELES-002",
211 Self::PointNotFound(_) => "VELES-003",
212 Self::DimensionMismatch { .. } => "VELES-004",
213 Self::InvalidVector(_) => "VELES-005",
214 Self::Storage(_) => "VELES-006",
215 Self::Index(_) => "VELES-007",
216 Self::IndexCorrupted(_) => "VELES-008",
217 Self::Config(_) => "VELES-009",
218 Self::Query(_) => "VELES-010",
219 Self::Io(_) => "VELES-011",
220 Self::Serialization(_) => "VELES-012",
221 Self::Internal(_) => "VELES-013",
222 Self::VectorNotAllowed(_) => "VELES-014",
223 Self::SearchNotSupported(_) => "VELES-015",
224 Self::VectorRequired(_) => "VELES-016",
225 Self::SchemaValidation(_) => "VELES-017",
226 Self::GraphNotSupported(_) => "VELES-018",
227 Self::EdgeExists(_) => "VELES-019",
228 Self::EdgeNotFound(_) => "VELES-020",
229 Self::InvalidEdgeLabel(_) => "VELES-021",
230 Self::NodeNotFound(_) => "VELES-022",
231 Self::Overflow(_) => "VELES-023",
232 Self::ColumnStoreError(_) => "VELES-024",
233 Self::GpuError(_) => "VELES-025",
234 Self::EpochMismatch(_) => "VELES-026",
235 Self::GuardRail(_) => "VELES-027",
236 Self::InvalidQuantizerConfig(_) => "VELES-028",
237 Self::TrainingFailed(_) => "VELES-029",
238 Self::SparseIndexError(_) => "VELES-030",
239 Self::DatabaseLocked(_) => "VELES-031",
240 Self::InvalidDimension { .. } => "VELES-032",
241 Self::AllocationFailed(_) => "VELES-033",
242 Self::InvalidCollectionName { .. } => "VELES-034",
243 }
244 }
245
246 #[must_use]
250 pub const fn is_recoverable(&self) -> bool {
251 !matches!(
252 self,
253 Self::IndexCorrupted(_)
254 | Self::Internal(_)
255 | Self::EpochMismatch(_)
256 | Self::AllocationFailed(_)
257 )
258 }
259}
260
261impl From<crate::velesql::ParseError> for Error {
263 fn from(err: crate::velesql::ParseError) -> Self {
264 Self::Query(err.to_string())
265 }
266}
267
268#[cfg(feature = "persistence")]
270impl From<crate::guardrails::GuardRailViolation> for Error {
271 fn from(v: crate::guardrails::GuardRailViolation) -> Self {
272 Self::GuardRail(v.to_string())
273 }
274}