Skip to main content

mcp_servers/coding/
error.rs

1//! Error types for coding tools
2//!
3//! This module provides structured error types for all coding tool operations,
4//! replacing the previous `Result<T, String>` pattern with proper `thiserror` enums.
5
6use thiserror::Error;
7
8pub use crate::file_ops::FileError;
9
10#[doc = include_str!("../docs/coding_error.md")]
11#[derive(Debug, Error)]
12pub enum CodingError {
13    /// File operation errors (read, write, edit)
14    #[error(transparent)]
15    File(#[from] FileError),
16
17    /// Bash command execution errors
18    #[error(transparent)]
19    Bash(#[from] BashError),
20
21    /// Grep search errors
22    #[error(transparent)]
23    Grep(#[from] GrepError),
24
25    /// ast-grep structural search errors
26    #[error(transparent)]
27    AstGrep(#[from] AstGrepError),
28
29    /// Find file errors
30    #[error(transparent)]
31    Find(#[from] FindError),
32
33    /// List files errors
34    #[error(transparent)]
35    ListFiles(#[from] ListFilesError),
36
37    /// Web fetch errors
38    #[error(transparent)]
39    WebFetch(#[from] WebFetchError),
40
41    /// Web search errors
42    #[error(transparent)]
43    WebSearch(#[from] WebSearchError),
44
45    /// Tool not configured/available
46    #[error("{0}")]
47    NotConfigured(String),
48}
49
50/// Errors related to bash command execution
51#[derive(Debug, Error)]
52pub enum BashError {
53    /// Command is forbidden (e.g., rm without flags)
54    #[error("{0}")]
55    Forbidden(String),
56
57    /// Timeout exceeds maximum allowed
58    #[error("Timeout cannot exceed 600000ms (10 minutes)")]
59    TimeoutTooLarge,
60
61    /// Failed to spawn process
62    #[error("Failed to execute command '{command}': {reason}")]
63    SpawnFailed { command: String, reason: String },
64
65    /// Invalid regex pattern for filtering
66    #[error("Invalid regex pattern: {0}")]
67    InvalidRegex(String),
68
69    /// Failed to join background task
70    #[error("Failed to join background task: {0}")]
71    JoinFailed(String),
72
73    /// Shell ID not found
74    #[error("Shell ID not found: {0}")]
75    ShellNotFound(String),
76
77    /// Wait on child process failed
78    #[error("Wait failed: {0}")]
79    WaitFailed(String),
80}
81
82/// Errors related to building glob filters, shared across search tools
83#[derive(Debug, Error)]
84pub enum GlobError {
85    /// Invalid glob pattern
86    #[error("Invalid glob pattern '{pattern}': {reason}")]
87    InvalidPattern { pattern: String, reason: String },
88
89    /// Failed to build glob set
90    #[error("Failed to build glob set: {0}")]
91    BuildFailed(String),
92}
93
94/// Errors related to grep search operations
95#[derive(Debug, Error)]
96pub enum GrepError {
97    /// Glob filter errors
98    #[error(transparent)]
99    Glob(#[from] GlobError),
100
101    /// Invalid regex pattern
102    #[error("Invalid regex pattern: {0}")]
103    InvalidRegex(String),
104
105    /// Search error during file processing
106    #[error("Search error: {0}")]
107    SearchFailed(String),
108
109    /// Search path does not exist
110    #[error("Search path does not exist: {0}")]
111    PathNotFound(String),
112}
113
114/// Errors related to ast-grep structural search operations
115#[derive(Debug, Error)]
116pub enum AstGrepError {
117    /// Search path does not exist
118    #[error("Search path does not exist: {0}")]
119    PathNotFound(String),
120
121    /// Glob filter errors
122    #[error(transparent)]
123    Glob(#[from] GlobError),
124
125    /// Unsupported ast-grep language
126    #[error("Unsupported ast-grep language: {0}")]
127    UnsupportedLanguage(String),
128
129    /// Invalid ast-grep pattern
130    #[error("Invalid ast-grep pattern: {0}")]
131    InvalidPattern(String),
132
133    /// Invalid regex in a capture constraint
134    #[error("Invalid regex for constraint '{name}': {reason}")]
135    InvalidConstraintRegex { name: String, reason: String },
136
137    /// Failed to read file
138    #[error("Failed to read file '{path}': {reason}")]
139    ReadFailed { path: String, reason: String },
140
141    /// Search failed during ast-grep processing
142    #[error("Search error: {0}")]
143    SearchFailed(String),
144}
145
146/// Errors related to find file operations
147#[derive(Debug, Error)]
148pub enum FindError {
149    /// Search path does not exist
150    #[error("Search path does not exist: {0}")]
151    PathNotFound(String),
152
153    /// Invalid glob pattern
154    #[error("Invalid glob pattern '{pattern}': {reason}")]
155    InvalidGlobPattern { pattern: String, reason: String },
156
157    /// Failed to lock results (mutex poisoned)
158    #[error("Failed to lock results")]
159    LockFailed,
160}
161
162/// Errors related to list files operations
163#[derive(Debug, Error)]
164pub enum ListFilesError {
165    /// Failed to read directory
166    #[error("Failed to read directory: {0}")]
167    ReadDirFailed(String),
168
169    /// Failed to read directory entry
170    #[error("Failed to read entry: {0}")]
171    ReadEntryFailed(String),
172
173    /// Failed to read metadata
174    #[error("Failed to read metadata: {0}")]
175    MetadataFailed(String),
176}
177
178/// Errors related to web fetch operations
179#[derive(Debug, Error)]
180pub enum WebFetchError {
181    /// Invalid URL format
182    #[error("Invalid URL: {0}")]
183    InvalidUrl(String),
184
185    /// HTTP request failed
186    #[error("Request failed: {0}")]
187    RequestFailed(String),
188
189    /// Request timed out
190    #[error("Request timed out after {0}ms")]
191    Timeout(u64),
192
193    /// Response too large
194    #[error("Response too large: {size} bytes exceeds limit of {limit} bytes")]
195    ResponseTooLarge { size: usize, limit: usize },
196
197    /// Failed to parse HTML content
198    #[error("Failed to parse HTML: {0}")]
199    ParseFailed(String),
200}
201
202/// Errors related to web search operations
203#[derive(Debug, Error)]
204pub enum WebSearchError {
205    /// Invalid search query
206    #[error("Invalid search query: {0}")]
207    InvalidQuery(String),
208
209    /// API request failed
210    #[error("API request failed: {0}")]
211    ApiError(String),
212
213    /// Rate limit exceeded
214    #[error("Rate limit exceeded: {0}")]
215    RateLimited(String),
216
217    /// Request timed out
218    #[error("Request timed out after {0}ms")]
219    Timeout(u64),
220
221    /// Configuration error
222    #[error("Configuration error: {0}")]
223    ConfigError(String),
224
225    /// Failed to parse API response
226    #[error("Failed to parse API response: {0}")]
227    ParseError(String),
228}