Skip to main content

serdes_ai_embeddings/
error.rs

1//! Embedding errors.
2
3use thiserror::Error;
4
5/// Errors that can occur during embedding operations.
6#[derive(Debug, Error)]
7pub enum EmbeddingError {
8    /// HTTP error from provider.
9    #[error("HTTP error {status}: {body}")]
10    Http {
11        /// HTTP status code.
12        status: u16,
13        /// Response body.
14        body: String,
15    },
16
17    /// API error from provider.
18    #[error("API error: {0}")]
19    Api(String),
20
21    /// Rate limited by provider.
22    #[error("Rate limited: retry after {retry_after:?}")]
23    RateLimited {
24        /// Suggested retry time.
25        retry_after: Option<std::time::Duration>,
26    },
27
28    /// Input too long.
29    #[error("Input too long: {length} tokens (max: {max})")]
30    InputTooLong {
31        /// Actual length.
32        length: usize,
33        /// Maximum allowed.
34        max: usize,
35    },
36
37    /// Feature not supported by this model.
38    #[error("Not supported: {0}")]
39    NotSupported(String),
40
41    /// Configuration error.
42    #[error("Configuration error: {0}")]
43    Config(String),
44
45    /// JSON serialization/deserialization error.
46    #[error("JSON error: {0}")]
47    Json(#[from] serde_json::Error),
48
49    /// Network/IO error.
50    #[error("IO error: {0}")]
51    Io(#[from] std::io::Error),
52
53    /// Other error.
54    #[error("{0}")]
55    Other(#[from] anyhow::Error),
56}
57
58impl EmbeddingError {
59    /// Create an API error.
60    pub fn api(msg: impl Into<String>) -> Self {
61        Self::Api(msg.into())
62    }
63
64    /// Create a config error.
65    pub fn config(msg: impl Into<String>) -> Self {
66        Self::Config(msg.into())
67    }
68
69    /// Check if this error is retryable.
70    pub fn is_retryable(&self) -> bool {
71        matches!(
72            self,
73            Self::RateLimited { .. }
74                | Self::Http {
75                    status: 429 | 500..=599,
76                    ..
77                }
78        )
79    }
80
81    /// Get suggested retry delay.
82    pub fn retry_after(&self) -> Option<std::time::Duration> {
83        match self {
84            Self::RateLimited { retry_after } => *retry_after,
85            _ => None,
86        }
87    }
88}
89
90/// Result type for embedding operations.
91pub type EmbeddingResult<T> = Result<T, EmbeddingError>;
92
93#[cfg(test)]
94mod tests {
95    use super::*;
96
97    #[test]
98    fn test_error_display() {
99        let err = EmbeddingError::api("invalid key");
100        assert!(err.to_string().contains("invalid key"));
101    }
102
103    #[test]
104    fn test_retryable() {
105        assert!(EmbeddingError::RateLimited { retry_after: None }.is_retryable());
106        assert!(EmbeddingError::Http {
107            status: 500,
108            body: String::new()
109        }
110        .is_retryable());
111        assert!(!EmbeddingError::Api("bad".into()).is_retryable());
112    }
113}