Skip to main content

llm_cascade/
error.rs

1//! Error types for provider and cascade operations.
2
3use std::path::PathBuf;
4use thiserror::Error;
5
6/// Errors from a single LLM provider request.
7#[derive(Debug, Error)]
8pub enum ProviderError {
9    /// The provider returned a non-success HTTP status.
10    #[error("HTTP {status}: {body}")]
11    Http {
12        /// HTTP status code.
13        status: u16,
14        /// Response body.
15        body: String,
16        /// Seconds to wait before retrying, if provided by the server.
17        retry_after: Option<u64>,
18    },
19
20    /// The HTTP request itself failed (network, DNS, TLS, etc.).
21    #[error("Request failed: {0}")]
22    Request(#[from] reqwest::Error),
23
24    /// The response body could not be parsed into the expected format.
25    #[error("Response parse error: {0}")]
26    Parse(String),
27
28    /// No API key was found for this provider.
29    #[error("API key not configured for provider '{0}'")]
30    MissingApiKey(String),
31
32    /// A catch-all for other provider-specific errors.
33    #[error("Provider error: {0}")]
34    Other(String),
35}
36
37impl ProviderError {
38    /// Returns the HTTP status code, if this was an HTTP error.
39    pub fn http_status(&self) -> Option<u16> {
40        match self {
41            ProviderError::Http { status, .. } => Some(*status),
42            _ => None,
43        }
44    }
45
46    /// Returns the `Retry-After` header value in seconds, if present.
47    pub fn retry_after_seconds(&self) -> Option<u64> {
48        match self {
49            ProviderError::Http { retry_after, .. } => *retry_after,
50            _ => None,
51        }
52    }
53
54    /// Returns `true` if the provider returned HTTP 429 (rate limited).
55    pub fn is_rate_limited(&self) -> bool {
56        matches!(self, ProviderError::Http { status: 429, .. })
57    }
58}
59
60/// All providers in a cascade failed.
61#[derive(Debug, Error)]
62#[error("All providers in cascade '{cascade_name}' failed: {message}\nFailed prompt persisted to: {}", .failed_prompt_path.display())]
63pub struct CascadeError {
64    /// Name of the cascade that failed.
65    pub cascade_name: String,
66    /// Combined error messages from each failed entry.
67    pub message: String,
68    /// Absolute path to the persisted `.json` file containing the failed conversation.
69    pub failed_prompt_path: PathBuf,
70}