Skip to main content

anthropic_tools/common/
errors.rs

1//! Error types for the Anthropic API client.
2//!
3//! This module provides error handling for the library, including:
4//!
5//! - [`AnthropicToolError`] - Main error type for all API errors
6//! - [`ErrorResponse`] - API error response structure
7//! - [`ErrorDetail`] - Detailed error information
8//! - [`Result`] - Type alias for `Result<T, AnthropicToolError>`
9//!
10//! # Error Types
11//!
12//! The API can return various error types:
13//!
14//! - `ApiKeyNotSet` - Missing API key
15//! - `InvalidRequestError` - Malformed request
16//! - `AuthenticationError` - Invalid API key
17//! - `RateLimitError` - Too many requests
18//! - `OverloadedError` - Server overloaded
19//!
20//! # Example
21//!
22//! ```rust
23//! use anthropic_tools::common::errors::{AnthropicToolError, Result};
24//!
25//! fn validate_api_key(key: &str) -> Result<()> {
26//!     if key.is_empty() {
27//!         return Err(AnthropicToolError::ApiKeyNotSet);
28//!     }
29//!     Ok(())
30//! }
31//! ```
32
33use serde::{Deserialize, Serialize};
34use thiserror::Error;
35
36/// Anthropic API error types
37#[derive(Error, Debug)]
38pub enum AnthropicToolError {
39    #[error("API key is not set. Set ANTHROPIC_API_KEY environment variable.")]
40    ApiKeyNotSet,
41
42    #[error("Missing required field: {0}")]
43    MissingRequiredField(String),
44
45    #[error("Invalid parameter: {0}")]
46    InvalidParameter(String),
47
48    #[error("HTTP request error: {0}")]
49    RequestError(#[from] request::Error),
50
51    #[error("JSON serialization/deserialization error: {0}")]
52    SerdeJsonError(#[from] serde_json::Error),
53
54    #[error("API error ({error_type}): {message}")]
55    ApiError {
56        error_type: String,
57        message: String,
58        request_id: Option<String>,
59    },
60
61    #[error("Invalid request error: {0}")]
62    InvalidRequestError(String),
63
64    #[error("Authentication error: {0}")]
65    AuthenticationError(String),
66
67    #[error("Permission error: {0}")]
68    PermissionError(String),
69
70    #[error("Not found error: {0}")]
71    NotFoundError(String),
72
73    #[error("Rate limit error: {0}")]
74    RateLimitError(String),
75
76    #[error("Overloaded error: {0}")]
77    OverloadedError(String),
78
79    #[error("IO error: {0}")]
80    IoError(#[from] std::io::Error),
81}
82
83pub type Result<T> = std::result::Result<T, AnthropicToolError>;
84
85/// Error response from Anthropic API
86#[derive(Debug, Clone, Serialize, Deserialize)]
87pub struct ErrorResponse {
88    #[serde(rename = "type")]
89    pub type_name: String,
90    pub error: ErrorDetail,
91    #[serde(skip_serializing_if = "Option::is_none")]
92    pub request_id: Option<String>,
93}
94
95/// Error detail in API error response
96#[derive(Debug, Clone, Serialize, Deserialize)]
97pub struct ErrorDetail {
98    #[serde(rename = "type")]
99    pub type_name: String,
100    pub message: String,
101}
102
103impl ErrorResponse {
104    /// Convert ErrorResponse to AnthropicToolError
105    pub fn into_error(self) -> AnthropicToolError {
106        let message = self.error.message.clone();
107        let request_id = self.request_id.clone();
108
109        match self.error.type_name.as_str() {
110            "invalid_request_error" => AnthropicToolError::InvalidRequestError(message),
111            "authentication_error" => AnthropicToolError::AuthenticationError(message),
112            "permission_error" => AnthropicToolError::PermissionError(message),
113            "not_found_error" => AnthropicToolError::NotFoundError(message),
114            "rate_limit_error" => AnthropicToolError::RateLimitError(message),
115            "overloaded_error" => AnthropicToolError::OverloadedError(message),
116            _ => AnthropicToolError::ApiError {
117                error_type: self.error.type_name,
118                message,
119                request_id,
120            },
121        }
122    }
123}