zoey_core/
error.rs

1//! Error types for ZoeyOS core
2
3use thiserror::Error;
4
5/// Main error type for ZoeyOS operations
6#[derive(Debug, Error)]
7pub enum ZoeyError {
8    /// Database operation error (from sqlx)
9    #[error("Database error: {0}")]
10    DatabaseSqlx(#[from] sqlx::Error),
11
12    /// Database operation error (custom message)
13    #[error("Database error: {0}")]
14    Database(String),
15
16    /// Plugin-related error
17    #[error("Plugin error: {0}")]
18    Plugin(String),
19
20    /// Runtime error
21    #[error("Runtime error: {0}")]
22    Runtime(String),
23
24    /// Model/LLM error
25    #[error("Model error: {0}")]
26    Model(String),
27
28    /// Memory operation error
29    #[error("Memory error: {0}")]
30    Memory(String),
31
32    /// Serialization/deserialization error
33    #[error("Serialization error: {0}")]
34    Serialization(#[from] serde_json::Error),
35
36    /// IO error
37    #[error("IO error: {0}")]
38    Io(#[from] std::io::Error),
39
40    /// Configuration error
41    #[error("Configuration error: {0}")]
42    Config(String),
43
44    /// Validation error
45    #[error("Validation error: {0}")]
46    Validation(String),
47
48    /// Network/HTTP error
49    #[error("Network error: {0}")]
50    Network(#[from] reqwest::Error),
51
52    /// Template rendering error
53    #[error("Template error: {0}")]
54    Template(String),
55
56    /// Service error
57    #[error("Service error: {0}")]
58    Service(String),
59
60    /// Event handling error
61    #[error("Event error: {0}")]
62    Event(String),
63
64    /// Action execution error
65    #[error("Action error: {0}")]
66    Action(String),
67
68    /// Provider error
69    #[error("Provider error: {0}")]
70    Provider(String),
71
72    /// Evaluator error
73    #[error("Evaluator error: {0}")]
74    Evaluator(String),
75
76    /// Not found error (generic)
77    #[error("Not found: {0}")]
78    NotFound(String),
79
80    /// Authentication/authorization error
81    #[error("Auth error: {0}")]
82    Auth(String),
83
84    /// Rate limit error
85    #[error("Rate limit exceeded: {0}")]
86    RateLimit(String),
87
88    /// Timeout error
89    #[error("Timeout: {0}")]
90    Timeout(String),
91
92    /// Generic error with context
93    #[error("{0}")]
94    Other(String),
95
96    /// Database constraint violation with details
97    #[error(
98        "Database constraint violation in table '{table}': {constraint} = '{value}'. {suggestion}"
99    )]
100    DatabaseConstraintViolation {
101        /// Database table name
102        table: String,
103        /// Constraint name
104        constraint: String,
105        /// Attempted value
106        value: String,
107        /// Suggestion for fixing
108        suggestion: String,
109    },
110
111    /// Vector search error
112    #[error(
113        "Vector search error: {message}. Dimension: {dimension}, Expected: {expected_dimension}"
114    )]
115    VectorSearch {
116        /// Error message
117        message: String,
118        /// Actual embedding dimension
119        dimension: usize,
120        /// Expected embedding dimension
121        expected_dimension: usize,
122    },
123
124    /// Missing required field
125    #[error("Missing required field '{field}' in {context}. {suggestion}")]
126    MissingField {
127        /// Field name
128        field: String,
129        /// Context where field is missing
130        context: String,
131        /// Suggestion for fixing
132        suggestion: String,
133    },
134
135    /// Resource exhausted
136    #[error("Resource '{resource}' exhausted: {message}. Current: {current}, Limit: {limit}")]
137    ResourceExhausted {
138        /// Resource name
139        resource: String,
140        /// Error message
141        message: String,
142        /// Current usage
143        current: usize,
144        /// Maximum limit
145        limit: usize,
146    },
147}
148
149/// Convenient Result type using ZoeyError
150pub type Result<T> = std::result::Result<T, ZoeyError>;
151
152impl ZoeyError {
153    /// Create a database error
154    pub fn database(msg: impl Into<String>) -> Self {
155        ZoeyError::Database(msg.into())
156    }
157
158    /// Create a plugin error
159    pub fn plugin(msg: impl Into<String>) -> Self {
160        ZoeyError::Plugin(msg.into())
161    }
162
163    /// Create a runtime error
164    pub fn runtime(msg: impl Into<String>) -> Self {
165        ZoeyError::Runtime(msg.into())
166    }
167
168    /// Create a model error
169    pub fn model(msg: impl Into<String>) -> Self {
170        ZoeyError::Model(msg.into())
171    }
172
173    /// Create a memory error
174    pub fn memory(msg: impl Into<String>) -> Self {
175        ZoeyError::Memory(msg.into())
176    }
177
178    /// Create a config error
179    pub fn config(msg: impl Into<String>) -> Self {
180        ZoeyError::Config(msg.into())
181    }
182
183    /// Create a validation error
184    pub fn validation(msg: impl Into<String>) -> Self {
185        ZoeyError::Validation(msg.into())
186    }
187
188    /// Create a service error
189    pub fn service(msg: impl Into<String>) -> Self {
190        ZoeyError::Service(msg.into())
191    }
192
193    /// Create an event error
194    pub fn event(msg: impl Into<String>) -> Self {
195        ZoeyError::Event(msg.into())
196    }
197
198    /// Create an action error
199    pub fn action(msg: impl Into<String>) -> Self {
200        ZoeyError::Action(msg.into())
201    }
202
203    /// Create a provider error
204    pub fn provider(msg: impl Into<String>) -> Self {
205        ZoeyError::Provider(msg.into())
206    }
207
208    /// Create an evaluator error
209    pub fn evaluator(msg: impl Into<String>) -> Self {
210        ZoeyError::Evaluator(msg.into())
211    }
212
213    /// Create a not found error
214    pub fn not_found(msg: impl Into<String>) -> Self {
215        ZoeyError::NotFound(msg.into())
216    }
217
218    /// Create an auth error
219    pub fn auth(msg: impl Into<String>) -> Self {
220        ZoeyError::Auth(msg.into())
221    }
222
223    /// Create a rate limit error
224    pub fn rate_limit(msg: impl Into<String>) -> Self {
225        ZoeyError::RateLimit(msg.into())
226    }
227
228    /// Create a timeout error
229    pub fn timeout(msg: impl Into<String>) -> Self {
230        ZoeyError::Timeout(msg.into())
231    }
232
233    /// Create a generic error
234    pub fn other(msg: impl Into<String>) -> Self {
235        ZoeyError::Other(msg.into())
236    }
237
238    /// Create a template error
239    pub fn template(msg: impl Into<String>) -> Self {
240        ZoeyError::Template(msg.into())
241    }
242
243    /// Create a constraint violation error
244    pub fn constraint_violation(
245        table: impl Into<String>,
246        constraint: impl Into<String>,
247        value: impl Into<String>,
248        suggestion: impl Into<String>,
249    ) -> Self {
250        ZoeyError::DatabaseConstraintViolation {
251            table: table.into(),
252            constraint: constraint.into(),
253            value: value.into(),
254            suggestion: suggestion.into(),
255        }
256    }
257
258    /// Create a vector search error
259    pub fn vector_search(
260        message: impl Into<String>,
261        dimension: usize,
262        expected_dimension: usize,
263    ) -> Self {
264        ZoeyError::VectorSearch {
265            message: message.into(),
266            dimension,
267            expected_dimension,
268        }
269    }
270
271    /// Create a missing field error
272    pub fn missing_field(
273        field: impl Into<String>,
274        context: impl Into<String>,
275        suggestion: impl Into<String>,
276    ) -> Self {
277        ZoeyError::MissingField {
278            field: field.into(),
279            context: context.into(),
280            suggestion: suggestion.into(),
281        }
282    }
283
284    /// Create a resource exhausted error
285    pub fn resource_exhausted(
286        resource: impl Into<String>,
287        message: impl Into<String>,
288        current: usize,
289        limit: usize,
290    ) -> Self {
291        ZoeyError::ResourceExhausted {
292            resource: resource.into(),
293            message: message.into(),
294            current,
295            limit,
296        }
297    }
298}
299
300#[cfg(test)]
301mod tests {
302    use super::*;
303
304    #[test]
305    fn test_error_creation() {
306        let err = ZoeyError::plugin("test plugin error");
307        assert_eq!(err.to_string(), "Plugin error: test plugin error");
308
309        let err = ZoeyError::runtime("test runtime error");
310        assert_eq!(err.to_string(), "Runtime error: test runtime error");
311    }
312
313    #[test]
314    fn test_result_type() {
315        fn returns_result() -> Result<i32> {
316            Ok(42)
317        }
318
319        assert_eq!(returns_result().unwrap(), 42);
320    }
321}