Skip to main content

weavatrix_search_vector/
error.rs

1use std::fmt;
2
3/// Typed build and query failures.
4#[derive(Debug, Clone, PartialEq, Eq)]
5#[non_exhaustive]
6pub enum SearchError {
7    /// The supplied [`crate::IndexConfig`] cannot construct a valid index.
8    InvalidConfig(&'static str),
9    /// A vector or query did not match the configured dimensionality.
10    DimensionMismatch {
11        /// Required number of components.
12        expected: usize,
13        /// Observed number of components.
14        actual: usize,
15        /// Input-vector position, or `None` when validating a query.
16        vector: Option<usize>,
17    },
18    /// A vector or query component was NaN or infinite.
19    NonFiniteValue {
20        /// Input-vector position, or `None` when validating a query.
21        vector: Option<usize>,
22        /// Position of the invalid component.
23        dimension: usize,
24    },
25    /// A stored vector or query had zero magnitude.
26    ZeroVector {
27        /// Input-vector position, or `None` when validating a query.
28        vector: Option<usize>,
29    },
30    /// More than one stored vector used the same caller-provided key.
31    DuplicateKey(u64),
32    /// More than one vector used the same key and per-key vector identifier.
33    DuplicateVectorId { key: u64, vector_id: u64 },
34    /// Index sizes or degree arithmetic exceeded supported capacity.
35    CapacityOverflow,
36    /// A fallible reservation for index or query storage failed.
37    AllocationFailed,
38    /// A bounded build or query worker panicked.
39    WorkerPanic,
40    /// A filesystem operation failed while reading or writing an index.
41    Storage {
42        /// Operation that failed.
43        operation: &'static str,
44        /// Portable operating-system error category.
45        kind: std::io::ErrorKind,
46    },
47    /// A persisted index failed structural or integrity validation.
48    CorruptSnapshot(&'static str),
49    /// The snapshot format is newer or older than this crate understands.
50    UnsupportedSnapshotVersion(u32),
51    /// A requested vector key was not present.
52    MissingKey(u64),
53    /// An embedding provider rejected an input or failed to produce a vector.
54    EmbeddingFailed(String),
55    /// A local or remote search shard failed.
56    ShardFailed {
57        /// Stable zero-based shard position.
58        shard: usize,
59        /// Provider-specific failure text.
60        message: String,
61    },
62    /// Mutations changed while an optimistic compaction was being built.
63    MutationConflict,
64}
65
66impl SearchError {
67    pub(crate) fn storage(operation: &'static str, error: &std::io::Error) -> Self {
68        Self::Storage {
69            operation,
70            kind: error.kind(),
71        }
72    }
73}
74
75impl fmt::Display for SearchError {
76    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
77        match self {
78            Self::InvalidConfig(message) => write!(formatter, "invalid index config: {message}"),
79            Self::DimensionMismatch {
80                expected,
81                actual,
82                vector,
83            } => match vector {
84                Some(vector) => write!(
85                    formatter,
86                    "vector {vector} has {actual} dimensions; expected {expected}"
87                ),
88                None => write!(
89                    formatter,
90                    "query has {actual} dimensions; expected {expected}"
91                ),
92            },
93            Self::NonFiniteValue { vector, dimension } => match vector {
94                Some(vector) => {
95                    write!(
96                        formatter,
97                        "vector {vector} has a non-finite value at dimension {dimension}"
98                    )
99                }
100                None => write!(
101                    formatter,
102                    "query has a non-finite value at dimension {dimension}"
103                ),
104            },
105            Self::ZeroVector {
106                vector: Some(vector),
107            } => {
108                write!(formatter, "vector {vector} has zero magnitude")
109            }
110            Self::ZeroVector { vector: None } => formatter.write_str("query has zero magnitude"),
111            Self::DuplicateKey(key) => write!(formatter, "duplicate vector key {key}"),
112            Self::DuplicateVectorId { key, vector_id } => {
113                write!(formatter, "duplicate vector id {vector_id} for key {key}")
114            }
115            Self::CapacityOverflow => formatter.write_str("index capacity arithmetic overflowed"),
116            Self::AllocationFailed => formatter.write_str("index allocation failed"),
117            Self::WorkerPanic => formatter.write_str("a bounded vector-search worker panicked"),
118            Self::Storage { operation, kind } => {
119                write!(
120                    formatter,
121                    "index storage operation {operation} failed: {kind}"
122                )
123            }
124            Self::CorruptSnapshot(message) => {
125                write!(formatter, "corrupt vector-index snapshot: {message}")
126            }
127            Self::UnsupportedSnapshotVersion(version) => {
128                write!(
129                    formatter,
130                    "unsupported vector-index snapshot version {version}"
131                )
132            }
133            Self::MissingKey(key) => write!(formatter, "vector key {key} was not found"),
134            Self::EmbeddingFailed(message) => {
135                write!(formatter, "embedding provider failed: {message}")
136            }
137            Self::ShardFailed { shard, message } => {
138                write!(formatter, "vector-search shard {shard} failed: {message}")
139            }
140            Self::MutationConflict => {
141                formatter.write_str("mutable index changed repeatedly during compaction")
142            }
143        }
144    }
145}
146
147impl std::error::Error for SearchError {}