1use serde::{Deserialize, Serialize};
4
5#[cfg(feature = "_api")]
6#[derive(Debug, thiserror::Error)]
7pub enum OpenAIError {
8 #[error("http error: {0}")]
10 Reqwest(#[from] reqwest::Error),
11 #[error("{0}")]
14 ApiError(ApiErrorResponse),
15 #[error("failed to deserialize api response: error:{0} content:{1}")]
17 JSONDeserialize(serde_json::Error, String),
18 #[cfg(all(feature = "_api", not(target_family = "wasm")))]
19 #[error("failed to save file: {0}")]
21 FileSaveError(String),
22 #[cfg(all(feature = "_api", not(target_family = "wasm")))]
23 #[error("failed to read file: {0}")]
25 FileReadError(String),
26 #[error("stream failed: {0}")]
28 StreamError(Box<StreamError>),
29 #[cfg(feature = "middleware")]
31 #[error(transparent)]
32 Boxed(Box<dyn std::error::Error + Send + Sync + 'static>),
33 #[error("invalid args: {0}")]
36 InvalidArgument(String),
37}
38
39#[cfg(all(feature = "_api", feature = "middleware"))]
40impl From<tower::BoxError> for OpenAIError {
41 fn from(error: tower::BoxError) -> Self {
42 OpenAIError::Boxed(error)
43 }
44}
45
46#[cfg(not(feature = "_api"))]
47#[derive(Debug)]
48pub enum OpenAIError {
49 InvalidArgument(String),
52}
53
54#[cfg(not(feature = "_api"))]
55impl std::fmt::Display for OpenAIError {
56 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
57 match self {
58 OpenAIError::InvalidArgument(msg) => write!(f, "invalid args: {}", msg),
59 }
60 }
61}
62
63#[cfg(not(feature = "_api"))]
64impl std::error::Error for OpenAIError {}
65
66#[cfg(feature = "_api")]
67#[derive(Debug, thiserror::Error)]
68pub enum StreamError {
69 #[error("Unknown event: {0:#?}")]
71 UnknownEvent(eventsource_stream::Event),
72 #[error("EventStream error: {0}")]
74 EventStream(String),
75}
76
77#[derive(Debug, Serialize, Deserialize, Clone)]
79pub struct ApiError {
80 pub message: String,
81 pub r#type: Option<String>,
82 pub param: Option<String>,
83 pub code: Option<String>,
84}
85
86impl std::fmt::Display for ApiError {
87 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
91 let mut parts = Vec::new();
92
93 if let Some(r#type) = &self.r#type {
94 parts.push(format!("{}:", r#type));
95 }
96
97 parts.push(self.message.clone());
98
99 if let Some(param) = &self.param {
100 parts.push(format!("(param: {param})"));
101 }
102
103 if let Some(code) = &self.code {
104 parts.push(format!("(code: {code})"));
105 }
106
107 write!(f, "{}", parts.join(" "))
108 }
109}
110
111impl std::error::Error for ApiError {}
112
113#[cfg(feature = "_api")]
115#[derive(Debug, Clone)]
116pub struct ApiErrorResponse {
117 pub status_code: reqwest::StatusCode,
119 pub api_error: ApiError,
121}
122
123#[cfg(feature = "_api")]
124impl std::fmt::Display for ApiErrorResponse {
125 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
126 write!(f, "{} {}", self.status_code, self.api_error)
127 }
128}
129
130#[cfg(feature = "_api")]
131impl std::error::Error for ApiErrorResponse {}
132
133#[derive(Debug, Deserialize, Serialize)]
135pub struct WrappedError {
136 pub error: ApiError,
137}
138
139#[cfg(feature = "_api")]
140pub(crate) fn map_deserialization_error(e: serde_json::Error, bytes: &[u8]) -> OpenAIError {
141 let json_content = String::from_utf8_lossy(bytes);
142 tracing::error!("failed deserialization of: {}", json_content);
143
144 OpenAIError::JSONDeserialize(e, json_content.to_string())
145}