Skip to main content

artificial_openai/
error.rs

1use std::str::Utf8Error;
2
3use artificial_core::error::ArtificialError;
4use reqwest::StatusCode;
5use std::time::Duration;
6
7/// Headers conveying rate limit information returned by OpenAI.
8#[derive(Debug, Clone)]
9pub struct OpenAiRateLimitHeaders {
10    pub limit_requests: Option<u32>,
11    pub remaining_requests: Option<u32>,
12    pub reset_requests: Option<String>,
13    pub limit_tokens: Option<u32>,
14    pub remaining_tokens: Option<u32>,
15    pub reset_tokens: Option<String>,
16}
17
18/// High-level error type covering every failure mode the client can hit.
19#[derive(Debug, thiserror::Error)]
20pub enum OpenAiError {
21    #[error("request failed: {0}")]
22    Http(#[from] reqwest::Error),
23
24    #[error("couldn’t serialise body: {0}")]
25    Serde(#[from] serde_json::Error),
26
27    #[error("rate limited (status {status}), retry_after={retry_after:?}, reset_at={reset_at:?}")]
28    RateLimited {
29        status: StatusCode,
30        body: String,
31        retry_after: Option<Duration>,
32        reset_at: Option<String>,
33        headers: OpenAiRateLimitHeaders,
34    },
35
36    #[error("OpenAI returned non-success status {status}: {body}")]
37    Api { status: StatusCode, body: String },
38
39    #[error("OpenAI format error: {0}")]
40    Format(String),
41
42    #[error("unknown error: {0}")]
43    Unknown(String),
44}
45
46impl From<OpenAiError> for ArtificialError {
47    fn from(value: OpenAiError) -> Self {
48        ArtificialError::Backend(Box::new(value))
49    }
50}
51
52impl From<Utf8Error> for OpenAiError {
53    fn from(value: Utf8Error) -> Self {
54        Self::Unknown(format!("UTF8 error: {value}"))
55    }
56}