specado_core/
error.rs

1use crate::auth::AuthError;
2use thiserror::Error;
3
4#[derive(Debug, Error)]
5pub enum Error {
6    #[error("Configuration error: {0}")]
7    Config(String),
8
9    #[error("Schema validation failed: {0}")]
10    SchemaValidation(String),
11
12    #[error("Provider error ({provider}): {kind:?}")]
13    Provider {
14        provider: String,
15        kind: ProviderErrorKind,
16    },
17
18    #[error("Transform error: {0}")]
19    Transform(String),
20
21    #[error("Strict mode violation")]
22    StrictModeViolation,
23
24    #[error("Circuit breaker is open")]
25    CircuitBreakerOpen,
26
27    #[error("Circuit breaker is half-open, rejecting request")]
28    CircuitBreakerHalfOpen,
29
30    #[error("HTTP error: {0}")]
31    Http(#[from] reqwest::Error),
32
33    #[error("JSON error: {0}")]
34    Json(#[from] serde_json::Error),
35
36    #[error("IO error: {0}")]
37    Io(#[from] std::io::Error),
38
39    #[error("Authentication error: {0}")]
40    Auth(#[from] AuthError),
41}
42
43#[derive(Debug, Clone, PartialEq, Eq)]
44pub enum ProviderErrorKind {
45    RateLimit,
46    Timeout,
47    InvalidRequest,
48    AuthenticationFailed,
49    ServerError,
50    Unknown,
51}
52
53pub type Result<T> = std::result::Result<T, Error>;
54
55#[cfg(test)]
56mod tests {
57    use super::*;
58    use crate::auth::AuthError;
59
60    #[test]
61    fn wraps_io_error() {
62        let err = std::io::Error::other("disk failed");
63        let wrapped = Error::from(err);
64        matches!(wrapped, Error::Io(_))
65            .then_some(())
66            .expect("io errors map to Error::Io");
67    }
68
69    #[test]
70    fn wraps_json_error() {
71        let err = serde_json::from_str::<serde_json::Value>("not-json").unwrap_err();
72        let wrapped = Error::from(err);
73        assert!(matches!(wrapped, Error::Json(_)));
74    }
75
76    #[test]
77    fn auth_error_converts() {
78        let auth_err = AuthError::MissingEnvVar("OPENAI_API_KEY".into());
79        let wrapped = Error::from(auth_err);
80        assert!(matches!(wrapped, Error::Auth(_)));
81    }
82
83    #[test]
84    fn provider_error_kind_debug() {
85        let kind = ProviderErrorKind::RateLimit;
86        assert_eq!(format!("{:?}", kind), "RateLimit");
87    }
88}