systemprompt_models/
errors.rs1pub use systemprompt_traits::RepositoryError;
2
3use crate::api::ApiError;
4
5#[derive(Debug, Clone, thiserror::Error)]
6pub enum CoreError {
7 #[error("Module config missing required field: {field}")]
8 MissingConfigField { field: String },
9
10 #[error("Invalid module version: {version}")]
11 InvalidVersion { version: String },
12
13 #[error("Module {name} configuration invalid: {reason}")]
14 InvalidModuleConfig { name: String, reason: String },
15
16 #[error("Module {name} not found")]
17 ModuleNotFound { name: String },
18
19 #[error("Invalid module field {field}: {reason}")]
20 InvalidField { field: String, reason: String },
21
22 #[error("Version comparison failed: {reason}")]
23 VersionComparisonFailed { reason: String },
24
25 #[error("Authentication failed: {reason}")]
26 AuthenticationFailed { reason: String },
27
28 #[error("Invalid or expired token")]
29 InvalidToken,
30
31 #[error("Token expired")]
32 TokenExpired,
33
34 #[error("Invalid token signature")]
35 InvalidSignature,
36
37 #[error("Missing required claim: {claim}")]
38 MissingClaim { claim: String },
39
40 #[error("Invalid authorization header")]
41 InvalidAuthHeader,
42
43 #[error("Invalid token format")]
44 InvalidTokenFormat,
45
46 #[error("Unauthorized")]
47 Unauthorized,
48
49 #[error("Forbidden: {reason}")]
50 Forbidden { reason: String },
51
52 #[error("User not found: {user_id}")]
53 UserNotFound { user_id: String },
54
55 #[error("Session not found: {session_id}")]
56 SessionNotFound { session_id: String },
57
58 #[error("Invalid session: {reason}")]
59 InvalidSession { reason: String },
60
61 #[error("Session expired")]
62 SessionExpired,
63
64 #[error("Cookie not found")]
65 CookieNotFound,
66
67 #[error("Invalid cookie format")]
68 InvalidCookieFormat,
69
70 #[error("Database error: {reason}")]
71 DatabaseError { reason: String },
72
73 #[error("Table not found: {table}")]
74 TableNotFound { table: String },
75
76 #[error("Schema error: {message}")]
77 SchemaError { message: String },
78
79 #[error("File not found: {path}")]
80 FileNotFound { path: String },
81
82 #[error("IO error: {reason}")]
83 IoError { reason: String },
84
85 #[error("Internal server error: {reason}")]
86 InternalError { reason: String },
87}
88
89impl CoreError {
90 pub fn reason(&self) -> String {
91 self.to_string()
92 }
93
94 pub const fn status_code(&self) -> u16 {
95 match self {
96 Self::AuthenticationFailed { .. }
97 | Self::InvalidToken
98 | Self::TokenExpired
99 | Self::InvalidSignature
100 | Self::Unauthorized
101 | Self::SessionExpired => 401,
102 Self::MissingClaim { .. }
103 | Self::InvalidAuthHeader
104 | Self::InvalidTokenFormat
105 | Self::InvalidSession { .. }
106 | Self::CookieNotFound
107 | Self::InvalidCookieFormat
108 | Self::MissingConfigField { .. }
109 | Self::InvalidVersion { .. }
110 | Self::InvalidModuleConfig { .. }
111 | Self::InvalidField { .. }
112 | Self::VersionComparisonFailed { .. } => 400,
113 Self::Forbidden { .. } => 403,
114 Self::UserNotFound { .. }
115 | Self::SessionNotFound { .. }
116 | Self::ModuleNotFound { .. }
117 | Self::TableNotFound { .. }
118 | Self::FileNotFound { .. } => 404,
119 Self::DatabaseError { .. }
120 | Self::SchemaError { .. }
121 | Self::IoError { .. }
122 | Self::InternalError { .. } => 500,
123 }
124 }
125
126 pub const fn is_client_error(&self) -> bool {
127 self.status_code() < 500
128 }
129
130 pub const fn is_server_error(&self) -> bool {
131 self.status_code() >= 500
132 }
133
134 pub const fn is_auth_error(&self) -> bool {
135 matches!(
136 self,
137 Self::AuthenticationFailed { .. }
138 | Self::InvalidToken
139 | Self::TokenExpired
140 | Self::InvalidSignature
141 | Self::InvalidAuthHeader
142 | Self::InvalidTokenFormat
143 | Self::Unauthorized
144 | Self::SessionExpired
145 )
146 }
147
148 pub const fn is_permission_error(&self) -> bool {
149 matches!(self, Self::Forbidden { .. })
150 }
151
152 pub const fn is_not_found(&self) -> bool {
153 matches!(
154 self,
155 Self::UserNotFound { .. }
156 | Self::SessionNotFound { .. }
157 | Self::ModuleNotFound { .. }
158 | Self::TableNotFound { .. }
159 | Self::FileNotFound { .. }
160 )
161 }
162}
163
164impl From<String> for CoreError {
165 fn from(reason: String) -> Self {
166 Self::InternalError { reason }
167 }
168}
169
170impl From<&str> for CoreError {
171 fn from(reason: &str) -> Self {
172 Self::InternalError {
173 reason: reason.to_string(),
174 }
175 }
176}
177
178impl From<anyhow::Error> for CoreError {
179 fn from(err: anyhow::Error) -> Self {
180 Self::InternalError {
181 reason: err.to_string(),
182 }
183 }
184}
185
186impl From<std::io::Error> for CoreError {
187 fn from(err: std::io::Error) -> Self {
188 Self::IoError {
189 reason: err.to_string(),
190 }
191 }
192}
193
194#[derive(Debug, thiserror::Error)]
195pub enum ServiceError {
196 #[error("repository error: {0}")]
197 Repository(#[from] RepositoryError),
198
199 #[error("validation error: {0}")]
200 Validation(String),
201
202 #[error("business logic error: {0}")]
203 BusinessLogic(String),
204
205 #[error("external service error: {0}")]
206 External(String),
207
208 #[error("not found: {0}")]
209 NotFound(String),
210
211 #[error("conflict: {0}")]
212 Conflict(String),
213
214 #[error("unauthorized: {0}")]
215 Unauthorized(String),
216
217 #[error("forbidden: {0}")]
218 Forbidden(String),
219}
220
221impl From<ServiceError> for ApiError {
222 fn from(err: ServiceError) -> Self {
223 match err {
224 ServiceError::Repository(e) => e.into(),
225 ServiceError::Validation(msg) | ServiceError::BusinessLogic(msg) => {
226 Self::bad_request(msg)
227 },
228 ServiceError::NotFound(msg) => Self::not_found(msg),
229 ServiceError::External(msg) => {
230 Self::internal_error(format!("External service error: {msg}"))
231 },
232 ServiceError::Conflict(msg) => Self::conflict(msg),
233 ServiceError::Unauthorized(msg) => Self::unauthorized(msg),
234 ServiceError::Forbidden(msg) => Self::forbidden(msg),
235 }
236 }
237}
238
239impl From<RepositoryError> for ApiError {
240 fn from(err: RepositoryError) -> Self {
241 match err {
242 RepositoryError::NotFound(msg) => Self::not_found(msg),
243 RepositoryError::InvalidData(msg) | RepositoryError::ConstraintViolation(msg) => {
244 Self::bad_request(msg)
245 },
246 RepositoryError::Database(e) => Self::internal_error(format!("Database error: {e}")),
247 RepositoryError::Serialization(e) => {
248 Self::internal_error(format!("Serialization error: {e}"))
249 },
250 RepositoryError::Other(e) => Self::internal_error(format!("Error: {e}")),
251 _ => Self::internal_error(format!("Repository error: {err}")),
252 }
253 }
254}