Skip to main content

iron_providers/
error.rs

1//! Provider error types
2//!
3//! Structured errors for common failure classes including authentication,
4//! transport, rate limiting, and malformed responses.
5
6use serde::{Deserialize, Serialize};
7use thiserror::Error;
8
9/// Result type alias for provider operations
10pub type ProviderResult<T> = Result<T, ProviderError>;
11
12/// Structured provider errors
13#[derive(Error, Debug, Clone, PartialEq, Serialize, Deserialize)]
14pub enum ProviderError {
15    /// Authentication failure (invalid or missing API key)
16    #[error("Authentication failed: {message}")]
17    Authentication { message: String },
18
19    /// Transport/connection failure
20    #[error("Transport error: {message}")]
21    Transport { message: String },
22
23    /// Rate limit exceeded
24    #[error("Rate limit exceeded: {message}")]
25    RateLimit {
26        message: String,
27        retry_after: Option<u64>,
28    },
29
30    /// Malformed response from provider
31    #[error("Malformed response: {message}")]
32    MalformedResponse { message: String },
33
34    /// Invalid request parameters
35    #[error("Invalid request: {message}")]
36    InvalidRequest { message: String },
37
38    /// Model not found or unsupported
39    #[error("Model error: {message}")]
40    Model { message: String },
41
42    /// General provider error (catch-all)
43    #[error("Provider error: {message}")]
44    General { message: String },
45}
46
47impl ProviderError {
48    /// Create an authentication error
49    pub fn auth<S: Into<String>>(message: S) -> Self {
50        Self::Authentication {
51            message: message.into(),
52        }
53    }
54
55    /// Create a transport error
56    pub fn transport<S: Into<String>>(message: S) -> Self {
57        Self::Transport {
58            message: message.into(),
59        }
60    }
61
62    /// Create a rate limit error
63    pub fn rate_limit<S: Into<String>>(message: S, retry_after: Option<u64>) -> Self {
64        Self::RateLimit {
65            message: message.into(),
66            retry_after,
67        }
68    }
69
70    /// Create a malformed response error
71    pub fn malformed<S: Into<String>>(message: S) -> Self {
72        Self::MalformedResponse {
73            message: message.into(),
74        }
75    }
76
77    /// Create an invalid request error
78    pub fn invalid_request<S: Into<String>>(message: S) -> Self {
79        Self::InvalidRequest {
80            message: message.into(),
81        }
82    }
83
84    /// Create a model error
85    pub fn model<S: Into<String>>(message: S) -> Self {
86        Self::Model {
87            message: message.into(),
88        }
89    }
90
91    /// Create a general error
92    pub fn general<S: Into<String>>(message: S) -> Self {
93        Self::General {
94            message: message.into(),
95        }
96    }
97
98    /// Check if this is an authentication error
99    pub fn is_authentication(&self) -> bool {
100        matches!(self, Self::Authentication { .. })
101    }
102
103    /// Check if this is a rate limit error
104    pub fn is_rate_limit(&self) -> bool {
105        matches!(self, Self::RateLimit { .. })
106    }
107
108    /// Check if this is a transport error
109    pub fn is_transport(&self) -> bool {
110        matches!(self, Self::Transport { .. })
111    }
112
113    /// Get retry-after duration if available
114    pub fn retry_after(&self) -> Option<u64> {
115        match self {
116            Self::RateLimit { retry_after, .. } => *retry_after,
117            _ => None,
118        }
119    }
120}