rag_plusplus_core/
error.rs

1//! RAG++ Error Types
2//!
3//! Structured error hierarchy for the entire library.
4//! All errors implement std::error::Error and can be converted to anyhow::Error.
5
6use thiserror::Error;
7
8/// Main error type for RAG++
9#[derive(Error, Debug)]
10pub enum Error {
11    // Index errors
12    #[error("Index not found: {name}")]
13    IndexNotFound { name: String },
14
15    #[error("Duplicate index: {name}")]
16    DuplicateIndex { name: String },
17
18    #[error("Dimension mismatch: expected {expected}, got {got}")]
19    DimensionMismatch { expected: usize, got: usize },
20
21    #[error("Index build failed: {reason}")]
22    IndexBuild { reason: String },
23
24    #[error("Index corrupted: {details}")]
25    IndexCorrupted { details: String },
26
27    #[error("Index capacity exceeded: {current}/{max}")]
28    IndexCapacity { current: usize, max: usize },
29
30    // Query errors
31    #[error("Invalid query: {reason}")]
32    InvalidQuery { reason: String },
33
34    #[error("Query timeout after {elapsed_ms}ms (budget: {budget_ms}ms)")]
35    QueryTimeout { elapsed_ms: u64, budget_ms: u64 },
36
37    #[error("Filter evaluation failed: {reason}")]
38    FilterError { reason: String },
39
40    // Storage errors
41    #[error("Record not found: {record_id}")]
42    RecordNotFound { record_id: String },
43
44    #[error("Duplicate record: {record_id}")]
45    DuplicateRecord { record_id: String },
46
47    #[error("Serialization failed: {reason}")]
48    Serialization { reason: String },
49
50    // WAL errors
51    #[error("WAL write failed: {reason}")]
52    WalWrite { reason: String },
53
54    #[error("WAL recovery failed: {reason}")]
55    WalRecovery { reason: String },
56
57    // Resource errors
58    #[error("Memory limit exceeded: {used_bytes}/{limit_bytes} bytes")]
59    MemoryLimit { used_bytes: usize, limit_bytes: usize },
60
61    #[error("IO error: {0}")]
62    Io(#[from] std::io::Error),
63}
64
65/// Result type alias using RAG++ Error
66pub type Result<T> = std::result::Result<T, Error>;
67
68impl Error {
69    /// Check if error is retriable
70    #[must_use]
71    pub const fn is_retriable(&self) -> bool {
72        matches!(
73            self,
74            Self::QueryTimeout { .. } | Self::Io(_) | Self::MemoryLimit { .. }
75        )
76    }
77
78    /// Get error code for metrics/logging
79    #[must_use]
80    pub const fn error_code(&self) -> &'static str {
81        match self {
82            Self::IndexNotFound { .. } => "INDEX_NOT_FOUND",
83            Self::DuplicateIndex { .. } => "DUPLICATE_INDEX",
84            Self::DimensionMismatch { .. } => "DIMENSION_MISMATCH",
85            Self::IndexBuild { .. } => "INDEX_BUILD_FAILED",
86            Self::IndexCorrupted { .. } => "INDEX_CORRUPTED",
87            Self::IndexCapacity { .. } => "INDEX_CAPACITY",
88            Self::InvalidQuery { .. } => "INVALID_QUERY",
89            Self::QueryTimeout { .. } => "QUERY_TIMEOUT",
90            Self::FilterError { .. } => "FILTER_ERROR",
91            Self::RecordNotFound { .. } => "RECORD_NOT_FOUND",
92            Self::DuplicateRecord { .. } => "DUPLICATE_RECORD",
93            Self::Serialization { .. } => "SERIALIZATION_ERROR",
94            Self::WalWrite { .. } => "WAL_WRITE_ERROR",
95            Self::WalRecovery { .. } => "WAL_RECOVERY_ERROR",
96            Self::MemoryLimit { .. } => "MEMORY_LIMIT",
97            Self::Io(_) => "IO_ERROR",
98        }
99    }
100}