Skip to main content

litellm_rs/sdk/
errors.rs

1//! Error handling
2
3use thiserror::Error;
4
5/// Error
6#[derive(Error, Debug)]
7pub enum SDKError {
8    /// Provider not found
9    #[error("Provider not found: {0}")]
10    ProviderNotFound(String),
11
12    /// Default
13    #[error("No default provider configured")]
14    NoDefaultProvider,
15
16    /// Error
17    #[error("Provider error: {0}")]
18    ProviderError(String),
19
20    /// Configuration
21    #[error("Configuration error: {0}")]
22    ConfigError(String),
23
24    /// Error
25    #[error("Network error: {0}")]
26    NetworkError(String),
27
28    /// Error
29    #[error("Authentication error: {0}")]
30    AuthError(String),
31
32    /// Error
33    #[error("Rate limit exceeded: {0}")]
34    RateLimitError(String),
35
36    /// Model
37    #[error("Model not found: {0}")]
38    ModelNotFound(String),
39
40    /// Feature not supported
41    #[error("Feature not supported: {0}")]
42    NotSupported(String),
43
44    /// Unsupported provider
45    #[error("Unsupported provider: {0}")]
46    UnsupportedProvider(String),
47
48    /// Error
49    #[error("Serialization error: {0}")]
50    SerializationError(#[from] serde_json::Error),
51
52    /// Error
53    #[error("HTTP error: {0}")]
54    HttpError(#[from] reqwest::Error),
55
56    /// Request
57    #[error("Invalid request: {0}")]
58    InvalidRequest(String),
59
60    /// Error
61    #[error("Internal error: {0}")]
62    Internal(String),
63
64    /// Error
65    #[error("API error: {0}")]
66    ApiError(String),
67
68    /// Error
69    #[error("Parse error: {0}")]
70    ParseError(String),
71}
72
73/// Error
74impl From<crate::utils::error::gateway_error::GatewayError> for SDKError {
75    fn from(error: crate::utils::error::gateway_error::GatewayError) -> Self {
76        match error {
77            crate::utils::error::gateway_error::GatewayError::Auth(msg) => SDKError::AuthError(msg),
78            crate::utils::error::gateway_error::GatewayError::NotFound(msg) => {
79                SDKError::ModelNotFound(msg)
80            }
81            crate::utils::error::gateway_error::GatewayError::BadRequest(msg) => {
82                SDKError::InvalidRequest(msg)
83            }
84            crate::utils::error::gateway_error::GatewayError::RateLimit { message, .. } => {
85                SDKError::RateLimitError(message)
86            }
87            crate::utils::error::gateway_error::GatewayError::Unavailable(msg) => {
88                SDKError::ProviderError(msg)
89            }
90            crate::utils::error::gateway_error::GatewayError::Internal(msg) => {
91                SDKError::Internal(msg)
92            }
93            crate::utils::error::gateway_error::GatewayError::Network(msg) => {
94                SDKError::NetworkError(msg)
95            }
96            crate::utils::error::gateway_error::GatewayError::Validation(msg) => {
97                SDKError::InvalidRequest(msg)
98            }
99            // Handle
100            _ => SDKError::Internal(error.to_string()),
101        }
102    }
103}
104
105// Temporarily disabled old provider error mapping
106/*
107impl From<crate::core::providers::ProviderError> for SDKError {
108    fn from(error: crate::core::providers::ProviderError) -> Self {
109        match error {
110            crate::core::providers::ProviderError::Authentication(msg) => SDKError::AuthError(msg),
111            crate::core::providers::ProviderError::RateLimit(msg) => SDKError::RateLimitError(msg),
112            crate::core::providers::ProviderError::RateLimited(msg) => {
113                SDKError::RateLimitError(msg)
114            }
115            crate::core::providers::ProviderError::ModelNotFound(msg) => {
116                SDKError::ModelNotFound(msg)
117            }
118            crate::core::providers::ProviderError::InvalidRequest(msg) => {
119                SDKError::InvalidRequest(msg)
120            }
121            crate::core::providers::ProviderError::Unavailable(msg) => SDKError::ProviderError(msg),
122            crate::core::providers::ProviderError::Network(msg) => SDKError::NetworkError(msg),
123            crate::core::providers::ProviderError::Parsing(msg) => SDKError::Internal(msg),
124            crate::core::providers::ProviderError::Timeout(msg) => SDKError::NetworkError(msg),
125            crate::core::providers::ProviderError::Other(msg) => SDKError::Internal(msg),
126            crate::core::providers::ProviderError::Unknown(msg) => SDKError::Internal(msg),
127        }
128    }
129}
130*/
131
132/// SDK result type
133pub type Result<T> = std::result::Result<T, SDKError>;
134
135impl SDKError {
136    /// Error
137    pub fn is_retryable(&self) -> bool {
138        matches!(
139            self,
140            SDKError::NetworkError(_) | SDKError::RateLimitError(_) | SDKError::ProviderError(_)
141        )
142    }
143
144    /// Error
145    pub fn is_auth_error(&self) -> bool {
146        matches!(self, SDKError::AuthError(_))
147    }
148
149    /// Configuration
150    pub fn is_config_error(&self) -> bool {
151        matches!(
152            self,
153            SDKError::ConfigError(_) | SDKError::ProviderNotFound(_) | SDKError::NoDefaultProvider
154        )
155    }
156}
157
158#[cfg(test)]
159mod tests {
160    use super::*;
161    use crate::utils::error::gateway_error::GatewayError;
162
163    // ==================== SDKError Display Tests ====================
164
165    #[test]
166    fn test_sdk_error_provider_not_found() {
167        let error = SDKError::ProviderNotFound("openai".to_string());
168        assert_eq!(error.to_string(), "Provider not found: openai");
169    }
170
171    #[test]
172    fn test_sdk_error_no_default_provider() {
173        let error = SDKError::NoDefaultProvider;
174        assert_eq!(error.to_string(), "No default provider configured");
175    }
176
177    #[test]
178    fn test_sdk_error_provider_error() {
179        let error = SDKError::ProviderError("API unavailable".to_string());
180        assert_eq!(error.to_string(), "Provider error: API unavailable");
181    }
182
183    #[test]
184    fn test_sdk_error_config_error() {
185        let error = SDKError::ConfigError("Missing API key".to_string());
186        assert_eq!(error.to_string(), "Configuration error: Missing API key");
187    }
188
189    #[test]
190    fn test_sdk_error_network_error() {
191        let error = SDKError::NetworkError("Connection refused".to_string());
192        assert_eq!(error.to_string(), "Network error: Connection refused");
193    }
194
195    #[test]
196    fn test_sdk_error_auth_error() {
197        let error = SDKError::AuthError("Invalid API key".to_string());
198        assert_eq!(error.to_string(), "Authentication error: Invalid API key");
199    }
200
201    #[test]
202    fn test_sdk_error_rate_limit_error() {
203        let error = SDKError::RateLimitError("Too many requests".to_string());
204        assert_eq!(error.to_string(), "Rate limit exceeded: Too many requests");
205    }
206
207    #[test]
208    fn test_sdk_error_model_not_found() {
209        let error = SDKError::ModelNotFound("gpt-5".to_string());
210        assert_eq!(error.to_string(), "Model not found: gpt-5");
211    }
212
213    #[test]
214    fn test_sdk_error_not_supported() {
215        let error = SDKError::NotSupported("streaming".to_string());
216        assert_eq!(error.to_string(), "Feature not supported: streaming");
217    }
218
219    #[test]
220    fn test_sdk_error_unsupported_provider() {
221        let error = SDKError::UnsupportedProvider("custom-provider".to_string());
222        assert_eq!(error.to_string(), "Unsupported provider: custom-provider");
223    }
224
225    #[test]
226    fn test_sdk_error_invalid_request() {
227        let error = SDKError::InvalidRequest("Missing messages".to_string());
228        assert_eq!(error.to_string(), "Invalid request: Missing messages");
229    }
230
231    #[test]
232    fn test_sdk_error_internal() {
233        let error = SDKError::Internal("Unexpected state".to_string());
234        assert_eq!(error.to_string(), "Internal error: Unexpected state");
235    }
236
237    #[test]
238    fn test_sdk_error_api_error() {
239        let error = SDKError::ApiError("Server returned 500".to_string());
240        assert_eq!(error.to_string(), "API error: Server returned 500");
241    }
242
243    #[test]
244    fn test_sdk_error_parse_error() {
245        let error = SDKError::ParseError("Invalid JSON".to_string());
246        assert_eq!(error.to_string(), "Parse error: Invalid JSON");
247    }
248
249    // ==================== SDKError is_retryable Tests ====================
250
251    #[test]
252    fn test_is_retryable_network_error() {
253        let error = SDKError::NetworkError("timeout".to_string());
254        assert!(error.is_retryable());
255    }
256
257    #[test]
258    fn test_is_retryable_rate_limit_error() {
259        let error = SDKError::RateLimitError("limit exceeded".to_string());
260        assert!(error.is_retryable());
261    }
262
263    #[test]
264    fn test_is_retryable_provider_error() {
265        let error = SDKError::ProviderError("unavailable".to_string());
266        assert!(error.is_retryable());
267    }
268
269    #[test]
270    fn test_is_not_retryable_auth_error() {
271        let error = SDKError::AuthError("invalid key".to_string());
272        assert!(!error.is_retryable());
273    }
274
275    #[test]
276    fn test_is_not_retryable_config_error() {
277        let error = SDKError::ConfigError("bad config".to_string());
278        assert!(!error.is_retryable());
279    }
280
281    #[test]
282    fn test_is_not_retryable_invalid_request() {
283        let error = SDKError::InvalidRequest("bad request".to_string());
284        assert!(!error.is_retryable());
285    }
286
287    #[test]
288    fn test_is_not_retryable_internal() {
289        let error = SDKError::Internal("bug".to_string());
290        assert!(!error.is_retryable());
291    }
292
293    // ==================== SDKError is_auth_error Tests ====================
294
295    #[test]
296    fn test_is_auth_error_true() {
297        let error = SDKError::AuthError("unauthorized".to_string());
298        assert!(error.is_auth_error());
299    }
300
301    #[test]
302    fn test_is_auth_error_false_for_others() {
303        let errors = vec![
304            SDKError::NetworkError("net".to_string()),
305            SDKError::ConfigError("cfg".to_string()),
306            SDKError::RateLimitError("rate".to_string()),
307            SDKError::Internal("int".to_string()),
308        ];
309
310        for error in errors {
311            assert!(!error.is_auth_error());
312        }
313    }
314
315    // ==================== SDKError is_config_error Tests ====================
316
317    #[test]
318    fn test_is_config_error_config_error() {
319        let error = SDKError::ConfigError("bad config".to_string());
320        assert!(error.is_config_error());
321    }
322
323    #[test]
324    fn test_is_config_error_provider_not_found() {
325        let error = SDKError::ProviderNotFound("xyz".to_string());
326        assert!(error.is_config_error());
327    }
328
329    #[test]
330    fn test_is_config_error_no_default_provider() {
331        let error = SDKError::NoDefaultProvider;
332        assert!(error.is_config_error());
333    }
334
335    #[test]
336    fn test_is_not_config_error_for_others() {
337        let errors = vec![
338            SDKError::NetworkError("net".to_string()),
339            SDKError::AuthError("auth".to_string()),
340            SDKError::RateLimitError("rate".to_string()),
341        ];
342
343        for error in errors {
344            assert!(!error.is_config_error());
345        }
346    }
347
348    // ==================== SDKError From GatewayError Tests ====================
349
350    #[test]
351    fn test_from_gateway_error_unauthorized() {
352        let gateway_error = GatewayError::Auth("Invalid token".to_string());
353        let sdk_error: SDKError = gateway_error.into();
354        assert!(matches!(sdk_error, SDKError::AuthError(_)));
355        assert!(sdk_error.is_auth_error());
356    }
357
358    #[test]
359    fn test_from_gateway_error_not_found() {
360        let gateway_error = GatewayError::NotFound("Resource not found".to_string());
361        let sdk_error: SDKError = gateway_error.into();
362        assert!(matches!(sdk_error, SDKError::ModelNotFound(_)));
363    }
364
365    #[test]
366    fn test_from_gateway_error_bad_request() {
367        let gateway_error = GatewayError::BadRequest("Invalid params".to_string());
368        let sdk_error: SDKError = gateway_error.into();
369        assert!(matches!(sdk_error, SDKError::InvalidRequest(_)));
370    }
371
372    #[test]
373    fn test_from_gateway_error_rate_limit() {
374        let gateway_error = GatewayError::RateLimit {
375            message: "Too many requests".to_string(),
376            retry_after: None,
377            rpm_limit: None,
378            tpm_limit: None,
379        };
380        let sdk_error: SDKError = gateway_error.into();
381        assert!(matches!(sdk_error, SDKError::RateLimitError(_)));
382        assert!(sdk_error.is_retryable());
383    }
384
385    #[test]
386    fn test_from_gateway_error_provider_unavailable() {
387        let gateway_error = GatewayError::Unavailable("OpenAI down".to_string());
388        let sdk_error: SDKError = gateway_error.into();
389        assert!(matches!(sdk_error, SDKError::ProviderError(_)));
390    }
391
392    #[test]
393    fn test_from_gateway_error_internal() {
394        let gateway_error = GatewayError::Internal("Unexpected error".to_string());
395        let sdk_error: SDKError = gateway_error.into();
396        assert!(matches!(sdk_error, SDKError::Internal(_)));
397    }
398
399    #[test]
400    fn test_from_gateway_error_network() {
401        let gateway_error = GatewayError::Network("Connection refused".to_string());
402        let sdk_error: SDKError = gateway_error.into();
403        assert!(matches!(sdk_error, SDKError::NetworkError(_)));
404        assert!(sdk_error.is_retryable());
405    }
406
407    #[test]
408    fn test_from_gateway_error_validation() {
409        let gateway_error = GatewayError::Validation("Invalid model".to_string());
410        let sdk_error: SDKError = gateway_error.into();
411        assert!(matches!(sdk_error, SDKError::InvalidRequest(_)));
412    }
413
414    #[test]
415    fn test_from_gateway_error_parsing() {
416        let gateway_error = GatewayError::Validation("Invalid JSON".to_string());
417        let sdk_error: SDKError = gateway_error.into();
418        assert!(matches!(sdk_error, SDKError::InvalidRequest(_)));
419    }
420
421    // ==================== SDKError Debug Tests ====================
422
423    #[test]
424    fn test_sdk_error_debug() {
425        let error = SDKError::AuthError("test".to_string());
426        let debug_str = format!("{:?}", error);
427        assert!(debug_str.contains("AuthError"));
428    }
429
430    #[test]
431    fn test_sdk_error_is_std_error() {
432        let error = SDKError::Internal("test".to_string());
433        let _: &dyn std::error::Error = &error;
434    }
435
436    // ==================== SDKError Edge Cases ====================
437
438    #[test]
439    fn test_sdk_error_empty_message() {
440        let error = SDKError::ProviderError("".to_string());
441        assert_eq!(error.to_string(), "Provider error: ");
442    }
443
444    #[test]
445    fn test_sdk_error_unicode() {
446        let error = SDKError::ApiError("错误信息 🚨".to_string());
447        assert!(error.to_string().contains("错误信息"));
448    }
449
450    #[test]
451    fn test_sdk_error_long_message() {
452        let long_msg = "a".repeat(1000);
453        let error = SDKError::Internal(long_msg.clone());
454        assert!(error.to_string().contains(&long_msg));
455    }
456}