Skip to main content

trueno_rag/
error.rs

1//! Error types for Trueno-RAG
2
3use thiserror::Error;
4
5/// Result type for Trueno-RAG operations
6pub type Result<T> = std::result::Result<T, Error>;
7
8/// Error types for RAG pipeline operations
9#[derive(Error, Debug)]
10pub enum Error {
11    /// Document is empty or invalid
12    #[error("empty document: {0}")]
13    EmptyDocument(String),
14
15    /// Chunk too large for processing
16    #[error("chunk exceeds maximum size: {size} > {max}")]
17    ChunkTooLarge {
18        /// Actual size
19        size: usize,
20        /// Maximum allowed size
21        max: usize,
22    },
23
24    /// Embedding dimension mismatch
25    #[error("embedding dimension mismatch: expected {expected}, got {actual}")]
26    DimensionMismatch {
27        /// Expected dimension
28        expected: usize,
29        /// Actual dimension
30        actual: usize,
31    },
32
33    /// Index not found
34    #[error("index not found: {0}")]
35    IndexNotFound(String),
36
37    /// Vector store error
38    #[error("vector store error: {0}")]
39    VectorStore(String),
40
41    /// Serialization error (serde_json)
42    #[error("serialization error: {0}")]
43    Serialization(#[from] serde_json::Error),
44
45    /// Serialization error (bincode/compression) - GH-2
46    #[error("serialization error: {0}")]
47    SerializationError(String),
48
49    /// IO error
50    #[error("IO error: {0}")]
51    Io(#[from] std::io::Error),
52
53    /// Invalid configuration
54    #[error("invalid configuration: {0}")]
55    InvalidConfig(String),
56
57    /// Query processing error
58    #[error("query error: {0}")]
59    Query(String),
60
61    /// Embedding error (GH-1: production embeddings)
62    #[error("embedding error: {0}")]
63    Embedding(String),
64
65    /// Invalid input error (PMAT-003: multi-vector)
66    #[error("invalid input: {0}")]
67    InvalidInput(String),
68}
69
70impl From<batuta_common::compression::CompressionError> for Error {
71    fn from(e: batuta_common::compression::CompressionError) -> Self {
72        Self::SerializationError(e.to_string())
73    }
74}
75
76#[cfg(test)]
77mod tests {
78    use super::*;
79
80    #[test]
81    fn test_error_display_empty_document() {
82        let err = Error::EmptyDocument("test.txt".to_string());
83        assert_eq!(err.to_string(), "empty document: test.txt");
84    }
85
86    #[test]
87    fn test_error_display_chunk_too_large() {
88        let err = Error::ChunkTooLarge { size: 1000, max: 512 };
89        assert_eq!(err.to_string(), "chunk exceeds maximum size: 1000 > 512");
90    }
91
92    #[test]
93    fn test_error_display_dimension_mismatch() {
94        let err = Error::DimensionMismatch { expected: 384, actual: 768 };
95        assert_eq!(err.to_string(), "embedding dimension mismatch: expected 384, got 768");
96    }
97
98    #[test]
99    fn test_error_from_io() {
100        let io_err = std::io::Error::new(std::io::ErrorKind::NotFound, "file not found");
101        let err = Error::from(io_err);
102        assert!(err.to_string().contains("file not found"));
103    }
104
105    #[test]
106    fn test_result_type() {
107        fn may_fail(succeed: bool) -> Result<i32> {
108            if succeed {
109                Ok(42)
110            } else {
111                Err(Error::InvalidConfig("test".to_string()))
112            }
113        }
114
115        assert_eq!(may_fail(true).unwrap(), 42);
116        assert!(may_fail(false).is_err());
117    }
118}