Skip to main content

alien_client_core/
error.rs

1use alien_error::AlienErrorData;
2use serde::{Deserialize, Serialize};
3
4/// Represents common infrastructure errors across multiple cloud platforms.
5#[derive(Debug, Clone, AlienErrorData, Serialize, Deserialize)]
6#[serde(rename_all = "camelCase")]
7pub enum ErrorData {
8    /// Invalid or malformed platform configuration.
9    #[error(
10        code = "INVALID_client_config",
11        message = "Invalid platform configuration: {message}",
12        retryable = "false",
13        internal = "false"
14    )]
15    InvalidClientConfig {
16        /// Human-readable description of the configuration issue
17        message: String,
18        /// Additional error details if available
19        errors: Option<String>,
20    },
21
22    /// Authentication with cloud provider failed.
23    #[error(
24        code = "AUTHENTICATION_ERROR",
25        message = "Authentication failed: {message}",
26        retryable = "true",
27        internal = "false"
28    )]
29    AuthenticationError {
30        /// Human-readable description of the authentication failure
31        message: String,
32    },
33
34    /// The requested resource does not exist.
35    #[error(
36        code = "REMOTE_RESOURCE_NOT_FOUND",
37        message = "{resource_type} '{resource_name}' not found",
38        retryable = "true",
39        internal = "false",
40        http_status_code = 404
41    )]
42    RemoteResourceNotFound {
43        /// Type of the resource that was not found
44        resource_type: String,
45        /// Name of the resource that was not found
46        resource_name: String,
47    },
48
49    /// Operation conflicts with current resource state (e.g., resource already exists, concurrent modifications, etag mismatch).
50    #[error(
51        code = "REMOTE_RESOURCE_CONFLICT",
52        message = "Conflict with {resource_type} '{resource_name}': {message}",
53        retryable = "true",
54        internal = "false"
55    )]
56    RemoteResourceConflict {
57        /// Type of the resource that has a conflict
58        resource_type: String,
59        /// Name of the resource that has a conflict
60        resource_name: String,
61        /// Human-readable description of the specific conflict
62        message: String,
63    },
64
65    /// Access denied due to insufficient permissions.
66    #[error(
67        code = "REMOTE_ACCESS_DENIED",
68        message = "Access denied to {resource_type} '{resource_name}'",
69        retryable = "true",
70        internal = "false"
71    )]
72    RemoteAccessDenied {
73        /// Type of the resource access was denied to
74        resource_type: String,
75        /// Name of the resource access was denied to
76        resource_name: String,
77    },
78
79    /// Request rate limit exceeded.
80    #[error(
81        code = "RATE_LIMIT_EXCEEDED",
82        message = "Rate limit exceeded: {message}",
83        retryable = "true",
84        internal = "false"
85    )]
86    RateLimitExceeded {
87        /// Human-readable description of the rate limit context
88        message: String,
89    },
90
91    /// Operation exceeded the allowed timeout.
92    #[error(
93        code = "TIMEOUT",
94        message = "Operation timed out: {message}",
95        retryable = "true",
96        internal = "false"
97    )]
98    Timeout {
99        /// Human-readable description of what operation timed out
100        message: String,
101    },
102
103    /// Service is temporarily unavailable.
104    #[error(
105        code = "REMOTE_SERVICE_UNAVAILABLE",
106        message = "Service unavailable: {message}",
107        retryable = "true",
108        internal = "false"
109    )]
110    RemoteServiceUnavailable {
111        /// Human-readable description of the service unavailability
112        message: String,
113    },
114
115    /// Quota or resource limits have been exceeded.
116    #[error(
117        code = "QUOTA_EXCEEDED",
118        message = "Quota exceeded: {message}",
119        retryable = "true",
120        internal = "false"
121    )]
122    QuotaExceeded {
123        /// Human-readable description of what quota was exceeded
124        message: String,
125    },
126
127    /// Network or request-level failure when sending HTTP request.
128    #[error(
129        code = "HTTP_REQUEST_FAILED",
130        message = "{message}",
131        retryable = "true",
132        internal = "false"
133    )]
134    HttpRequestFailed {
135        /// Human-readable description of the HTTP request failure
136        message: String,
137    },
138
139    /// HTTP request succeeded but returned a non-success status code.
140    #[error(
141        code = "HTTP_RESPONSE_ERROR",
142        message = "{message}",
143        retryable = "true",
144        internal = "false"
145    )]
146    HttpResponseError {
147        /// Human-readable description of the HTTP response error
148        message: String,
149        /// The URL that returned the error
150        url: String,
151        /// HTTP status code returned
152        http_status: u16,
153        // Request body text
154        http_request_text: Option<String>,
155        /// Response body text if available
156        http_response_text: Option<String>,
157    },
158
159    /// Failure during signing of an HTTP request (e.g., AWS SigV4).
160    #[error(
161        code = "REQUEST_SIGN_ERROR",
162        message = "Request signing failed: {message}",
163        retryable = "true",
164        internal = "true"
165    )]
166    RequestSignError {
167        /// Human-readable description of the signing failure
168        message: String,
169    },
170
171    /// Catch-all error
172    #[error(
173        code = "GENERIC_ERROR",
174        message = "{message}",
175        retryable = "true",
176        internal = "true"
177    )]
178    GenericError {
179        /// Human-readable description of the error
180        message: String,
181    },
182
183    /// Invalid or malformed input parameters provided to the operation.
184    #[error(
185        code = "INVALID_INPUT",
186        message = "Invalid input: {message}",
187        retryable = "false",
188        internal = "false"
189    )]
190    InvalidInput {
191        /// Human-readable description of what input was invalid
192        message: String,
193        /// Optional field name that was invalid
194        field_name: Option<String>,
195    },
196
197    /// Failed to serialize or deserialize data.
198    #[error(
199        code = "SERIALIZATION_ERROR",
200        message = "Serialization failed: {message}",
201        retryable = "false",
202        internal = "true"
203    )]
204    SerializationError {
205        /// Human-readable description of the serialization failure
206        message: String,
207    },
208
209    /// Failed to load or parse kubeconfig file.
210    #[error(
211        code = "KUBECONFIG_ERROR",
212        message = "Kubeconfig error: {message}",
213        retryable = "false",
214        internal = "false"
215    )]
216    KubeconfigError {
217        /// Human-readable description of the kubeconfig error
218        message: String,
219    },
220
221    /// Failed to load data from base64 or file.
222    #[error(
223        code = "DATA_LOAD_ERROR",
224        message = "Failed to load data: {message}",
225        retryable = "false",
226        internal = "false"
227    )]
228    DataLoadError {
229        /// Human-readable description of the data loading failure
230        message: String,
231    },
232}
233
234/// Convenient alias with default error type `ErrorData`. Allows callers to override the
235/// error type when needed while still accepting the common single-generic form `Result<T>`.
236pub type Result<T, E = ErrorData> = alien_error::Result<T, E>;
237
238/// Convenience alias representing a constructed AlienError with our `ErrorData` payload.
239pub type Error = alien_error::AlienError<ErrorData>;