Skip to main content

crates_docs/error/
mod.rs

1//! Error handling module
2//!
3//! Defines application error types and result type alias.
4//!
5//! # Error Types
6//!
7//! Provides various error variants covering initialization, configuration, HTTP requests, cache, etc.
8//!
9//! # Example
10//!
11//! ```rust
12//! use crates_docs::error::{Error, Result};
13//!
14//! fn may_fail() -> Result<String> {
15//!     // Operation that may fail
16//!     Ok("success".to_string())
17//! }
18//!
19//! // Create structured error
20//! fn create_config_error() -> Error {
21//!     Error::config("field_name", "invalid value")
22//! }
23//!
24//! fn create_cache_error() -> Error {
25//!     Error::cache("set", Some("key".to_string()), "operation failed")
26//! }
27//! ```
28
29use thiserror::Error;
30
31/// Application error type
32///
33/// Contains all possible error variants, implements `std::error::Error` via `thiserror` derive macro.
34#[derive(Error, Debug)]
35pub enum Error {
36    /// HTTP request error
37    #[error("HTTP request failed: {method} {url} - status {status}: {message}")]
38    HttpRequest {
39        /// HTTP method
40        method: String,
41        /// Request URL
42        url: String,
43        /// HTTP status code
44        status: u16,
45        /// Error message
46        message: String,
47    },
48
49    /// Cache operation error
50    #[error("Cache operation '{operation}' failed for key '{key}': {message}")]
51    Cache {
52        /// Operation type ("get", "set", "delete", "clear")
53        operation: String,
54        /// Cache key
55        key: String,
56        /// Error message
57        message: String,
58    },
59
60    /// MCP protocol error
61    #[error("MCP protocol error in '{context}': {message}")]
62    Mcp {
63        /// Context where error occurred
64        context: String,
65        /// Error message
66        message: String,
67    },
68
69    /// Initialization error
70    #[error("Initialization failed for '{component}': {message}")]
71    Initialization {
72        /// Component that failed initialization
73        component: String,
74        /// Error message
75        message: String,
76    },
77
78    /// Configuration error
79    #[error("Configuration error for '{field}': {message}")]
80    Config {
81        /// Configuration field name
82        field: String,
83        /// Error message
84        message: String,
85    },
86
87    /// Parse error
88    #[error("Parse failed for '{input}'{position}: {message}")]
89    Parse {
90        /// Input source being parsed
91        input: String,
92        /// Position information
93        position: String,
94        /// Error message
95        message: String,
96    },
97
98    /// Authentication error
99    #[error("Authentication failed for '{provider}': {message}")]
100    Auth {
101        /// Authentication provider
102        provider: String,
103        /// Error message
104        message: String,
105    },
106
107    /// IO error
108    #[error("IO error: {0}")]
109    Io(#[from] std::io::Error),
110
111    /// JSON serialization/deserialization error
112    #[error("JSON error: {0}")]
113    Json(#[from] serde_json::Error),
114
115    /// URL parse error
116    #[error("URL parse error: {0}")]
117    Url(#[from] url::ParseError),
118
119    /// Reqwest HTTP client error
120    #[error("HTTP client error: {0}")]
121    Reqwest(#[from] reqwest::Error),
122
123    /// Other error
124    #[error("Unknown error: {0}")]
125    Other(String),
126}
127
128/// Result type alias
129///
130/// `Result<T>` is shorthand for `std::result::Result<T, Error>`.
131pub type Result<T> = std::result::Result<T, Error>;
132
133impl Error {
134    /// Create HTTP request error
135    ///
136    /// # Arguments
137    ///
138    /// * `method` - HTTP method (GET, POST, etc.)
139    /// * `url` - Request URL
140    /// * `status` - HTTP status code
141    /// * `message` - Error message
142    #[must_use]
143    pub fn http_request(
144        method: impl Into<String>,
145        url: impl Into<String>,
146        status: u16,
147        message: impl Into<String>,
148    ) -> Self {
149        Self::HttpRequest {
150            method: method.into(),
151            url: url.into(),
152            status,
153            message: message.into(),
154        }
155    }
156
157    /// Create cache operation error
158    ///
159    /// # Arguments
160    ///
161    /// * `operation` - Operation type ("get", "set", "delete", "clear")
162    /// * `key` - Related cache key (optional)
163    /// * `message` - Error message
164    #[must_use]
165    pub fn cache(
166        operation: impl Into<String>,
167        key: Option<String>,
168        message: impl Into<String>,
169    ) -> Self {
170        Self::Cache {
171            operation: operation.into(),
172            key: key.unwrap_or_else(|| "N/A".to_string()),
173            message: message.into(),
174        }
175    }
176
177    /// Create MCP protocol error
178    ///
179    /// # Arguments
180    ///
181    /// * `context` - Context where error occurred
182    /// * `message` - Error message
183    #[must_use]
184    pub fn mcp(context: impl Into<String>, message: impl Into<String>) -> Self {
185        Self::Mcp {
186            context: context.into(),
187            message: message.into(),
188        }
189    }
190
191    /// Create initialization error
192    ///
193    /// # Arguments
194    ///
195    /// * `component` - Component that failed initialization
196    /// * `message` - Error message
197    #[must_use]
198    pub fn initialization(component: impl Into<String>, message: impl Into<String>) -> Self {
199        Self::Initialization {
200            component: component.into(),
201            message: message.into(),
202        }
203    }
204
205    /// Create configuration error
206    ///
207    /// # Arguments
208    ///
209    /// * `field` - Configuration field name
210    /// * `message` - Error message
211    #[must_use]
212    pub fn config(field: impl Into<String>, message: impl Into<String>) -> Self {
213        Self::Config {
214            field: field.into(),
215            message: message.into(),
216        }
217    }
218
219    /// Create parse error
220    ///
221    /// # Arguments
222    ///
223    /// * `input` - Input source being parsed
224    /// * `position` - Error position (optional)
225    /// * `message` - Error message
226    #[must_use]
227    pub fn parse(
228        input: impl Into<String>,
229        position: Option<usize>,
230        message: impl Into<String>,
231    ) -> Self {
232        Self::Parse {
233            input: input.into(),
234            position: position.map_or_else(String::new, |p| format!(" at position {p}")),
235            message: message.into(),
236        }
237    }
238
239    /// Create authentication error
240    ///
241    /// # Arguments
242    ///
243    /// * `provider` - Authentication provider
244    /// * `message` - Error message
245    #[must_use]
246    pub fn auth(provider: impl Into<String>, message: impl Into<String>) -> Self {
247        Self::Auth {
248            provider: provider.into(),
249            message: message.into(),
250        }
251    }
252}
253
254impl From<Box<dyn std::error::Error + Send + Sync>> for Error {
255    fn from(err: Box<dyn std::error::Error + Send + Sync>) -> Self {
256        Error::Other(err.to_string())
257    }
258}
259
260impl From<anyhow::Error> for Error {
261    fn from(err: anyhow::Error) -> Self {
262        Error::Other(err.to_string())
263    }
264}