1use alien_error::AlienErrorData;
2use serde::{Deserialize, Serialize};
3
4use crate::ResourceType;
5
6#[derive(Debug, Clone, AlienErrorData, Serialize, Deserialize)]
8#[serde(rename_all = "camelCase")]
9pub enum ErrorData {
10 #[error(
12 code = "GENERIC_ERROR",
13 message = "{message}",
14 retryable = "true",
15 internal = "false"
16 )]
17 GenericError {
18 message: String,
20 },
21
22 #[error(
24 code = "UNEXPECTED_RESOURCE_TYPE",
25 message = "Unexpected resource type for resource '{resource_id}': expected {expected}, but got {actual}",
26 retryable = "false",
27 internal = "false"
28 )]
29 UnexpectedResourceType {
30 resource_id: String,
31 expected: ResourceType,
32 actual: ResourceType,
33 },
34
35 #[error(
37 code = "INVALID_RESOURCE_UPDATE",
38 message = "Resource '{resource_id}' cannot be updated: {reason}",
39 retryable = "false",
40 internal = "false"
41 )]
42 InvalidResourceUpdate { resource_id: String, reason: String },
43
44 #[error(
46 code = "RESOURCE_HAS_NO_OUTPUTS",
47 message = "Resource '{resource_id}' has no outputs",
48 retryable = "true",
49 internal = "false"
50 )]
51 ResourceHasNoOutputs { resource_id: String },
52
53 #[error(
55 code = "RESOURCE_NOT_FOUND",
56 message = "Resource '{resource_id}' not found in stack state. Available resources: {available_resources:?}",
57 retryable = "false",
58 internal = "false",
59 http_status_code = 404
60 )]
61 ResourceNotFound {
62 resource_id: String,
63 available_resources: Vec<String>,
64 },
65
66 #[error(
68 code = "BINDING_CONFIG_INVALID",
69 message = "Invalid binding configuration for '{binding_name}': {reason}",
70 retryable = "false",
71 internal = "false"
72 )]
73 BindingConfigInvalid {
74 binding_name: String,
75 reason: String,
76 },
77
78 #[error(
80 code = "BINDING_ENV_VAR_MISSING",
81 message = "Missing environment variable '{env_var}' for binding '{binding_name}'",
82 retryable = "false",
83 internal = "false"
84 )]
85 BindingEnvVarMissing {
86 binding_name: String,
87 env_var: String,
88 },
89
90 #[error(
92 code = "BINDING_JSON_PARSE_FAILED",
93 message = "Failed to parse binding JSON for '{binding_name}': {reason}",
94 retryable = "false",
95 internal = "false"
96 )]
97 BindingJsonParseFailed {
98 binding_name: String,
99 reason: String,
100 },
101
102 #[error(
104 code = "UNEXPECTED_RESOURCE_STATUS_COMBINATION",
105 message = "Unexpected resource status combination during {operation}: {resource_statuses:?}",
106 retryable = "false",
107 internal = "true"
108 )]
109 UnexpectedResourceStatusCombination {
110 resource_statuses: Vec<String>,
111 operation: String,
112 },
113
114 #[error(
116 code = "EXTERNAL_BINDING_TYPE_MISMATCH",
117 message = "External binding type mismatch for resource '{resource_id}': expected {expected}, got {actual}",
118 retryable = "false",
119 internal = "false"
120 )]
121 ExternalBindingTypeMismatch {
122 resource_id: String,
123 expected: String,
124 actual: String,
125 },
126
127 #[error(
130 code = "PRESIGNED_REQUEST_EXPIRED",
131 message = "Presigned request for '{path}' expired at {expired_at}",
132 retryable = "false",
133 internal = "false"
134 )]
135 PresignedRequestExpired {
136 path: String,
137 expired_at: chrono::DateTime<chrono::Utc>,
138 },
139
140 #[error(
142 code = "HTTP_REQUEST_FAILED",
143 message = "HTTP {method} request to '{url}' failed",
144 retryable = "true",
145 internal = "false"
146 )]
147 HttpRequestFailed { url: String, method: String },
148
149 #[error(
151 code = "OPERATION_NOT_SUPPORTED",
152 message = "Operation '{operation}' not supported: {reason}",
153 retryable = "false",
154 internal = "false"
155 )]
156 OperationNotSupported { operation: String, reason: String },
157
158 #[error(
160 code = "LOCAL_FILESYSTEM_ERROR",
161 message = "Local filesystem error for '{path}' during {operation}",
162 retryable = "false",
163 internal = "false"
164 )]
165 LocalFilesystemError { path: String, operation: String },
166
167 #[error(
169 code = "FEATURE_NOT_ENABLED",
170 message = "Feature '{feature}' is not enabled",
171 retryable = "false",
172 internal = "false"
173 )]
174 FeatureNotEnabled { feature: String },
175
176 #[error(
179 code = "INVALID_ENVELOPE",
180 message = "Invalid ARC envelope: {message}",
181 retryable = "false",
182 internal = "false"
183 )]
184 InvalidEnvelope {
185 message: String,
186 field: Option<String>,
187 },
188
189 #[error(
191 code = "JSON_SERIALIZATION_FAILED",
192 message = "Failed to serialize JSON: {reason}",
193 retryable = "false",
194 internal = "false"
195 )]
196 JsonSerializationFailed { reason: String },
197}
198
199pub type Result<T> = alien_error::Result<T, ErrorData>;