agentik_sdk/types/
errors.rs1use thiserror::Error;
2
3#[derive(Error, Debug, Clone)]
4pub enum AnthropicError {
5 #[error("Bad request: {message}")]
6 BadRequest { message: String, status: u16 },
7
8 #[error("Authentication failed: {message}")]
9 Authentication { message: String, status: u16 },
10
11 #[error("Permission denied: {message}")]
12 PermissionDenied { message: String, status: u16 },
13
14 #[error("Resource not found: {message}")]
15 NotFound { message: String, status: u16 },
16
17 #[error("Unprocessable entity: {message}")]
18 UnprocessableEntity { message: String, status: u16 },
19
20 #[error("Rate limit exceeded: {message}")]
21 RateLimit { message: String, status: u16 },
22
23 #[error("Internal server error: {message}")]
24 InternalServer { message: String, status: u16 },
25
26 #[error("API connection error: {message}")]
27 Connection { message: String },
28
29 #[error("API connection timeout")]
30 ConnectionTimeout,
31
32 #[error("User aborted request")]
33 UserAbort,
34
35 #[error("Streaming error: {0}")]
36 StreamError(String),
37
38 #[error("Invalid configuration: {message}")]
39 Configuration { message: String },
40
41 #[error("Invalid API key")]
42 InvalidApiKey,
43
44 #[error("Request timeout")]
45 Timeout,
46
47 #[error("Network error: {0}")]
48 NetworkError(String),
49
50 #[error("HTTP error: {status} - {message}")]
51 HttpError { status: u16, message: String },
52
53 #[error("Service unavailable: {message}")]
54 ServiceUnavailable { message: String },
55
56 #[error("{0}")]
57 Other(String),
58}
59
60impl AnthropicError {
61 pub fn from_status(status: u16, message: String) -> Self {
63 match status {
64 400 => Self::BadRequest { message, status },
65 401 => Self::Authentication { message, status },
66 403 => Self::PermissionDenied { message, status },
67 404 => Self::NotFound { message, status },
68 422 => Self::UnprocessableEntity { message, status },
69 429 => Self::RateLimit { message, status },
70 500..=599 => Self::InternalServer { message, status },
71 _ => Self::InternalServer { message, status },
72 }
73 }
74
75 pub fn status_code(&self) -> Option<u16> {
77 match self {
78 Self::BadRequest { status, .. } |
79 Self::Authentication { status, .. } |
80 Self::PermissionDenied { status, .. } |
81 Self::NotFound { status, .. } |
82 Self::UnprocessableEntity { status, .. } |
83 Self::RateLimit { status, .. } |
84 Self::InternalServer { status, .. } => Some(*status),
85 _ => None,
86 }
87 }
88}
89
90impl From<reqwest::Error> for AnthropicError {
91 fn from(err: reqwest::Error) -> Self {
92 if err.is_timeout() {
93 Self::Timeout
94 } else if err.is_connect() {
95 Self::Connection {
96 message: err.to_string()
97 }
98 } else if err.is_request() {
99 Self::HttpError {
100 status: err.status().map(|s| s.as_u16()).unwrap_or(0),
101 message: err.to_string()
102 }
103 } else {
104 Self::NetworkError(err.to_string())
105 }
106 }
107}
108
109impl From<serde_json::Error> for AnthropicError {
110 fn from(err: serde_json::Error) -> Self {
111 Self::Other(format!("JSON serialization/deserialization error: {}", err))
112 }
113}
114
115impl From<chrono::OutOfRangeError> for AnthropicError {
116 fn from(err: chrono::OutOfRangeError) -> Self {
117 Self::Other(format!("Date/time out of range error: {}", err))
118 }
119}
120
121pub type Result<T> = std::result::Result<T, AnthropicError>;