airsprotocols_mcp/protocol/
errors.rs

1//! Error Types - Consolidated Protocol Error Handling
2//!
3//! This module consolidates error types from multiple sources:
4//! - `src/shared/protocol/errors.rs` (MCP protocol errors)
5//! - `src/transport/mcp/error.rs` (MCP transport errors)
6//! - Error handling patterns from `src/base/jsonrpc/` (JSON-RPC errors)
7//!
8//! # Consolidation Strategy
9//!
10//! **Phase 2 Migration Plan:**
11//! - Consolidate all protocol-related error types into a unified hierarchy
12//! - Preserve specific error context and diagnostic information
13//! - Maintain error conversion traits for backward compatibility
14//! - Follow Rust error handling best practices
15//!
16//! # Architecture Goals
17//!
18//! - **Comprehensive Coverage**: Handle all protocol error scenarios
19//! - **Type Safety**: Strong typing for different error categories
20//! - **Diagnostic Information**: Rich error context for debugging
21//! - **Conversion Support**: Easy conversion between error types
22
23// Layer 1: Standard library imports
24// (None required for current thiserror implementation)
25
26// Layer 2: Third-party crate imports
27use serde::{Deserialize, Serialize};
28use thiserror::Error;
29
30// Layer 3: Internal module imports
31use crate::protocol::transport::TransportError;
32// (Will be added during Phase 2 migration)
33
34// PHASE 1: Placeholder implementations
35// These will be replaced with actual consolidated implementations in Phase 2
36
37/// Placeholder for Protocol Error enumeration
38/// Will be populated with actual implementation during Phase 2 migration
39#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Error)]
40pub enum ProtocolError {
41    /// JSON-RPC related errors
42    #[error("JSON-RPC error: {message}")]
43    JsonRpc { message: String },
44
45    /// MCP protocol specific errors
46    #[error("MCP protocol error: {message}")]
47    Mcp { message: String },
48
49    /// Transport layer errors
50    #[error("Transport error: {message}")]
51    Transport { message: String },
52
53    /// Serialization/deserialization errors
54    #[error("Serialization error: {message}")]
55    Serialization { message: String },
56
57    /// Invalid message format errors
58    #[error("Invalid message: {message}")]
59    InvalidMessage { message: String },
60
61    /// Invalid base64 data
62    #[error("Invalid base64 data")]
63    InvalidBase64Data,
64
65    /// Invalid protocol version
66    #[error("Invalid protocol version: {0}")]
67    InvalidProtocolVersion(String),
68
69    /// Invalid URI format
70    #[error("Invalid URI: {0}")]
71    InvalidUri(String),
72
73    /// Invalid MIME type format
74    #[error("Invalid MIME type: {0}")]
75    InvalidMimeType(String),
76}
77
78/// Convenient result type for protocol operations
79pub type ProtocolResult<T> = Result<T, ProtocolError>;
80
81impl From<serde_json::Error> for ProtocolError {
82    fn from(err: serde_json::Error) -> Self {
83        Self::Serialization {
84            message: err.to_string(),
85        }
86    }
87}
88
89impl From<TransportError> for ProtocolError {
90    fn from(err: TransportError) -> Self {
91        Self::Transport {
92            message: err.to_string(),
93        }
94    }
95}
96
97/// Placeholder for JSON-RPC specific errors
98/// Will be populated with actual implementation during Phase 2 migration
99#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Error)]
100pub enum JsonRpcError {
101    /// Parse error (-32700)
102    #[error("Parse error: {message}")]
103    ParseError { message: String },
104
105    /// Invalid request (-32600)
106    #[error("Invalid request: {message}")]
107    InvalidRequest { message: String },
108
109    /// Method not found (-32601)
110    #[error("Method not found: {method}")]
111    MethodNotFound { method: String },
112
113    /// Invalid parameters (-32602)
114    #[error("Invalid parameters: {message}")]
115    InvalidParams { message: String },
116
117    /// Internal error (-32603)
118    #[error("Internal error: {message}")]
119    InternalError { message: String },
120
121    /// Server error (custom error codes)
122    #[error("Server error {code}: {message}")]
123    ServerError { code: i32, message: String },
124}
125
126/// Placeholder for MCP specific errors
127/// Will be populated with actual implementation during Phase 2 migration
128#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Error)]
129pub enum McpError {
130    /// Protocol version mismatch
131    #[error("Protocol version mismatch: expected {expected}, got {actual}")]
132    VersionMismatch { expected: String, actual: String },
133
134    /// Capability not supported
135    #[error("Unsupported capability: {capability}")]
136    UnsupportedCapability { capability: String },
137
138    /// Resource not found
139    #[error("Resource not found: {uri}")]
140    ResourceNotFound { uri: String },
141
142    /// Authorization failed
143    #[error("Authorization failed: {reason}")]
144    AuthorizationFailed { reason: String },
145
146    /// Invalid URI format
147    #[error("Invalid URI: {uri} - {reason}")]
148    InvalidUri { uri: String, reason: String },
149
150    /// Request timeout
151    #[error("Request timeout after {timeout_ms}ms")]
152    RequestTimeout { timeout_ms: u64 },
153}
154
155// Convenience constructors and JSON-RPC error code mappings
156impl JsonRpcError {
157    /// JSON-RPC 2.0 error codes as defined in the specification
158    pub const PARSE_ERROR: i32 = -32700;
159    pub const INVALID_REQUEST: i32 = -32600;
160    pub const METHOD_NOT_FOUND: i32 = -32601;
161    pub const INVALID_PARAMS: i32 = -32602;
162    pub const INTERNAL_ERROR: i32 = -32603;
163
164    /// Get the JSON-RPC error code for this error
165    pub fn error_code(&self) -> i32 {
166        match self {
167            JsonRpcError::ParseError { .. } => Self::PARSE_ERROR,
168            JsonRpcError::InvalidRequest { .. } => Self::INVALID_REQUEST,
169            JsonRpcError::MethodNotFound { .. } => Self::METHOD_NOT_FOUND,
170            JsonRpcError::InvalidParams { .. } => Self::INVALID_PARAMS,
171            JsonRpcError::InternalError { .. } => Self::INTERNAL_ERROR,
172            JsonRpcError::ServerError { code, .. } => *code,
173        }
174    }
175
176    /// Create a parse error
177    pub fn parse_error(message: impl Into<String>) -> Self {
178        Self::ParseError {
179            message: message.into(),
180        }
181    }
182
183    /// Create an invalid request error
184    pub fn invalid_request(message: impl Into<String>) -> Self {
185        Self::InvalidRequest {
186            message: message.into(),
187        }
188    }
189
190    /// Create a method not found error
191    pub fn method_not_found(method: impl Into<String>) -> Self {
192        Self::MethodNotFound {
193            method: method.into(),
194        }
195    }
196
197    /// Create an invalid parameters error
198    pub fn invalid_params(message: impl Into<String>) -> Self {
199        Self::InvalidParams {
200            message: message.into(),
201        }
202    }
203
204    /// Create an internal error
205    pub fn internal_error(message: impl Into<String>) -> Self {
206        Self::InternalError {
207            message: message.into(),
208        }
209    }
210
211    /// Create a server error with custom code
212    pub fn server_error(code: i32, message: impl Into<String>) -> Self {
213        Self::ServerError {
214            code,
215            message: message.into(),
216        }
217    }
218}
219
220// Convenience constructors for ProtocolError
221impl ProtocolError {
222    /// Create a JSON-RPC error
223    pub fn jsonrpc(message: impl Into<String>) -> Self {
224        Self::JsonRpc {
225            message: message.into(),
226        }
227    }
228
229    /// Create an MCP protocol error
230    pub fn mcp(message: impl Into<String>) -> Self {
231        Self::Mcp {
232            message: message.into(),
233        }
234    }
235
236    /// Create a transport error
237    pub fn transport(message: impl Into<String>) -> Self {
238        Self::Transport {
239            message: message.into(),
240        }
241    }
242
243    /// Create an invalid message error
244    pub fn invalid_message(message: impl Into<String>) -> Self {
245        Self::InvalidMessage {
246            message: message.into(),
247        }
248    }
249}
250
251// Convenience constructors for McpError
252impl McpError {
253    /// Create a version mismatch error
254    pub fn version_mismatch(expected: impl Into<String>, actual: impl Into<String>) -> Self {
255        Self::VersionMismatch {
256            expected: expected.into(),
257            actual: actual.into(),
258        }
259    }
260
261    /// Create an unsupported capability error
262    pub fn unsupported_capability(capability: impl Into<String>) -> Self {
263        Self::UnsupportedCapability {
264            capability: capability.into(),
265        }
266    }
267
268    /// Create a resource not found error
269    pub fn resource_not_found(uri: impl Into<String>) -> Self {
270        Self::ResourceNotFound { uri: uri.into() }
271    }
272
273    /// Create an authorization failed error
274    pub fn authorization_failed(reason: impl Into<String>) -> Self {
275        Self::AuthorizationFailed {
276            reason: reason.into(),
277        }
278    }
279
280    /// Create an invalid URI error
281    pub fn invalid_uri(uri: impl Into<String>, reason: impl Into<String>) -> Self {
282        Self::InvalidUri {
283            uri: uri.into(),
284            reason: reason.into(),
285        }
286    }
287
288    /// Create a request timeout error
289    pub fn request_timeout(timeout_ms: u64) -> Self {
290        Self::RequestTimeout { timeout_ms }
291    }
292}