1use thiserror::Error;
3
4#[derive(Debug, Error)]
6pub enum VectorError {
7 #[error("index error: {0}")]
9 Index(String),
10
11 #[error("store error: {0}")]
13 Store(Box<sqlx::Error>),
14
15 #[error("embedding error: {0}")]
17 Embedding(String),
18
19 #[error("gRPC error: {0}")]
21 Grpc(Box<tonic::Status>),
22
23 #[error("collection '{name}': {reason}")]
25 Collection {
26 name: String,
28 reason: String,
30 },
31
32 #[error("dimension mismatch: expected {expected}, got {got}")]
34 DimensionMismatch {
35 expected: usize,
37 got: usize,
39 },
40
41 #[error("serialization error: {0}")]
43 Serialization(Box<serde_json::Error>),
44
45 #[error("io error: {0}")]
47 Io(Box<std::io::Error>),
48
49 #[error("config error: {0}")]
51 Config(String),
52
53 #[error("search error: {0}")]
55 SearchError(String),
56
57 #[error("filter error: {0}")]
59 FilterError(String),
60
61 #[error("{entity} with id '{id}' not found")]
63 NotFound {
64 entity: String,
66 id: String,
68 },
69}
70
71impl VectorError {
72 pub fn is_not_found(&self) -> bool {
74 matches!(self, VectorError::NotFound { .. })
75 }
76
77 pub fn is_dimension_mismatch(&self) -> bool {
79 matches!(self, VectorError::DimensionMismatch { .. })
80 }
81
82 pub fn is_collection_error(&self) -> bool {
84 matches!(self, VectorError::Collection { .. })
85 }
86}
87
88impl From<sqlx::Error> for VectorError {
89 fn from(value: sqlx::Error) -> Self {
90 VectorError::Store(Box::new(value))
91 }
92}
93
94impl From<tonic::Status> for VectorError {
95 fn from(value: tonic::Status) -> Self {
96 VectorError::Grpc(Box::new(value))
97 }
98}
99
100impl From<serde_json::Error> for VectorError {
101 fn from(value: serde_json::Error) -> Self {
102 VectorError::Serialization(Box::new(value))
103 }
104}
105
106impl From<std::io::Error> for VectorError {
107 fn from(value: std::io::Error) -> Self {
108 VectorError::Io(Box::new(value))
109 }
110}
111
112impl From<VectorError> for tonic::Status {
113 fn from(e: VectorError) -> tonic::Status {
114 match &e {
115 VectorError::NotFound { entity, id } => {
116 tonic::Status::not_found(format!("{entity} '{id}' not found"))
117 }
118 VectorError::DimensionMismatch { expected, got } => tonic::Status::invalid_argument(
119 format!("dimension mismatch: expected {expected}, got {got}"),
120 ),
121 VectorError::Collection { name, reason } => {
122 tonic::Status::invalid_argument(format!("collection '{name}': {reason}"))
123 }
124 VectorError::Config(msg) => tonic::Status::invalid_argument(msg.clone()),
125 VectorError::Embedding(msg) => tonic::Status::internal(msg.clone()),
126 VectorError::Index(msg) => tonic::Status::internal(msg.clone()),
127 VectorError::SearchError(msg) => tonic::Status::internal(msg.clone()),
128 VectorError::FilterError(msg) => tonic::Status::internal(msg.clone()),
129 VectorError::Grpc(status) => status.as_ref().clone(),
130 _ => tonic::Status::internal(e.to_string()),
131 }
132 }
133}
134
135pub type VectorResult<T> = Result<T, VectorError>;