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}