1use std::any::Any;
16use std::sync::Arc;
17
18use common_error::ext::{BoxedError, ErrorExt};
19use common_error::status_code::StatusCode;
20use common_macro::stack_trace_debug;
21use datatypes::prelude::ConcreteDataType;
22use snafu::{Location, Snafu};
23use store_api::region_request::RegionRequest;
24use store_api::storage::RegionId;
25
26#[derive(Snafu)]
27#[snafu(visibility(pub))]
28#[stack_trace_debug]
29pub enum Error {
30 #[snafu(display("Failed to create mito region, region type: {}", region_type))]
31 CreateMitoRegion {
32 region_type: String,
33 source: BoxedError,
34 #[snafu(implicit)]
35 location: Location,
36 },
37
38 #[snafu(display("Failed to open mito region, region type: {}", region_type))]
39 OpenMitoRegion {
40 region_type: String,
41 source: BoxedError,
42 #[snafu(implicit)]
43 location: Location,
44 },
45
46 #[snafu(display("Failed to batch open mito region"))]
47 BatchOpenMitoRegion {
48 source: BoxedError,
49 #[snafu(implicit)]
50 location: Location,
51 },
52
53 #[snafu(display("Failed to batch catchup mito region"))]
54 BatchCatchupMitoRegion {
55 source: BoxedError,
56 #[snafu(implicit)]
57 location: Location,
58 },
59
60 #[snafu(display("No open region result for region {}", region_id))]
61 NoOpenRegionResult {
62 region_id: RegionId,
63 #[snafu(implicit)]
64 location: Location,
65 },
66
67 #[snafu(display("Failed to close mito region, region id: {}", region_id))]
68 CloseMitoRegion {
69 region_id: RegionId,
70 source: BoxedError,
71 #[snafu(implicit)]
72 location: Location,
73 },
74
75 #[snafu(display("Failed to deserialize column metadata from {}", raw))]
76 DeserializeColumnMetadata {
77 raw: String,
78 #[snafu(source)]
79 error: serde_json::Error,
80 #[snafu(implicit)]
81 location: Location,
82 },
83
84 #[snafu(display("Failed to serialize column metadata"))]
85 SerializeColumnMetadata {
86 #[snafu(source)]
87 error: serde_json::Error,
88 #[snafu(implicit)]
89 location: Location,
90 },
91
92 #[snafu(display("Failed to serialize region manifest info"))]
93 SerializeRegionManifestInfo {
94 #[snafu(source)]
95 error: serde_json::Error,
96 #[snafu(implicit)]
97 location: Location,
98 },
99
100 #[snafu(display("Failed to decode base64 column value"))]
101 DecodeColumnValue {
102 #[snafu(source)]
103 error: base64::DecodeError,
104 #[snafu(implicit)]
105 location: Location,
106 },
107
108 #[snafu(display("Failed to parse region id from {}", raw))]
109 ParseRegionId {
110 raw: String,
111 #[snafu(source)]
112 error: <u64 as std::str::FromStr>::Err,
113 #[snafu(implicit)]
114 location: Location,
115 },
116
117 #[snafu(display("Failed to parse region options: {}", reason))]
118 ParseRegionOptions {
119 reason: String,
120 #[snafu(implicit)]
121 location: Location,
122 },
123
124 #[snafu(display("Mito read operation fails"))]
125 MitoReadOperation {
126 source: BoxedError,
127 #[snafu(implicit)]
128 location: Location,
129 },
130
131 #[snafu(display("Failed to encode primary key"))]
132 EncodePrimaryKey {
133 source: mito_codec::error::Error,
134 #[snafu(implicit)]
135 location: Location,
136 },
137
138 #[snafu(display("Mito write operation fails"))]
139 MitoWriteOperation {
140 source: BoxedError,
141 #[snafu(implicit)]
142 location: Location,
143 },
144
145 #[snafu(display("Mito flush operation fails"))]
146 MitoFlushOperation {
147 source: BoxedError,
148 #[snafu(implicit)]
149 location: Location,
150 },
151
152 #[snafu(display("Mito sync operation fails"))]
153 MitoSyncOperation {
154 source: BoxedError,
155 #[snafu(implicit)]
156 location: Location,
157 },
158
159 #[snafu(display("Mito enter staging operation fails"))]
160 MitoEnterStagingOperation {
161 source: BoxedError,
162 #[snafu(implicit)]
163 location: Location,
164 },
165
166 #[snafu(display("Failed to collect record batch stream"))]
167 CollectRecordBatchStream {
168 source: common_recordbatch::error::Error,
169 #[snafu(implicit)]
170 location: Location,
171 },
172
173 #[snafu(display("Internal column {} is reserved", column))]
174 InternalColumnOccupied {
175 column: String,
176 #[snafu(implicit)]
177 location: Location,
178 },
179
180 #[snafu(display("Required table option is missing"))]
181 MissingRegionOption {
182 #[snafu(implicit)]
183 location: Location,
184 },
185
186 #[snafu(display("Region options are conflicted"))]
187 ConflictRegionOption {
188 #[snafu(implicit)]
189 location: Location,
190 },
191
192 #[snafu(display("Physical region {} not found", region_id))]
193 PhysicalRegionNotFound {
194 region_id: RegionId,
195 #[snafu(implicit)]
196 location: Location,
197 },
198
199 #[snafu(display("Logical region {} not found", region_id))]
200 LogicalRegionNotFound {
201 region_id: RegionId,
202 #[snafu(implicit)]
203 location: Location,
204 },
205
206 #[snafu(display("Column type mismatch. Expect {:?}, got {:?}", expect, actual))]
207 ColumnTypeMismatch {
208 expect: ConcreteDataType,
209 actual: ConcreteDataType,
210 #[snafu(implicit)]
211 location: Location,
212 },
213
214 #[snafu(display("Column {} not found in logical region {}", name, region_id))]
215 ColumnNotFound {
216 name: String,
217 region_id: RegionId,
218 #[snafu(implicit)]
219 location: Location,
220 },
221
222 #[snafu(display("Alter request to physical region is forbidden"))]
223 ForbiddenPhysicalAlter {
224 #[snafu(implicit)]
225 location: Location,
226 },
227
228 #[snafu(display("Invalid region metadata"))]
229 InvalidMetadata {
230 source: store_api::metadata::MetadataError,
231 #[snafu(implicit)]
232 location: Location,
233 },
234
235 #[snafu(display(
236 "Physical region {} is busy, there are still some logical regions using it",
237 region_id
238 ))]
239 PhysicalRegionBusy {
240 region_id: RegionId,
241 #[snafu(implicit)]
242 location: Location,
243 },
244
245 #[snafu(display("Unsupported region request: {}", request))]
246 UnsupportedRegionRequest {
247 request: Box<RegionRequest>,
248 #[snafu(implicit)]
249 location: Location,
250 },
251
252 #[snafu(display("Unsupported remap manifests request for region {}", region_id))]
253 UnsupportedRemapManifestsRequest {
254 region_id: RegionId,
255 #[snafu(implicit)]
256 location: Location,
257 },
258
259 #[snafu(display("Unsupported alter kind: {}", kind))]
260 UnsupportedAlterKind {
261 kind: String,
262 #[snafu(implicit)]
263 location: Location,
264 },
265
266 #[snafu(display("Multiple field column found: {} and {}", previous, current))]
267 MultipleFieldColumn {
268 previous: String,
269 current: String,
270 #[snafu(implicit)]
271 location: Location,
272 },
273
274 #[snafu(display("Adding field column {} to physical table", name))]
275 AddingFieldColumn {
276 name: String,
277 #[snafu(implicit)]
278 location: Location,
279 },
280
281 #[snafu(display("No field column found"))]
282 NoFieldColumn {
283 #[snafu(implicit)]
284 location: Location,
285 },
286
287 #[snafu(display("Failed to set SKIPPING index option"))]
288 SetSkippingIndexOption {
289 source: datatypes::error::Error,
290 #[snafu(implicit)]
291 location: Location,
292 },
293
294 #[snafu(display("Unexpected request: {}", reason))]
295 UnexpectedRequest {
296 reason: String,
297 #[snafu(implicit)]
298 location: Location,
299 },
300
301 #[snafu(display("Expected metric manifest info, region: {}", region_id))]
302 MetricManifestInfo {
303 region_id: RegionId,
304 #[snafu(implicit)]
305 location: Location,
306 },
307
308 #[snafu(display("Failed to start repeated task: {}", name))]
309 StartRepeatedTask {
310 name: String,
311 source: common_runtime::error::Error,
312 #[snafu(implicit)]
313 location: Location,
314 },
315
316 #[snafu(display("Get value from cache"))]
317 CacheGet {
318 source: Arc<Error>,
319 #[snafu(implicit)]
320 location: Location,
321 },
322}
323
324pub type Result<T, E = Error> = std::result::Result<T, E>;
325
326impl ErrorExt for Error {
327 fn status_code(&self) -> StatusCode {
328 use Error::*;
329
330 match self {
331 InternalColumnOccupied { .. }
332 | MissingRegionOption { .. }
333 | ConflictRegionOption { .. }
334 | ColumnTypeMismatch { .. }
335 | PhysicalRegionBusy { .. }
336 | MultipleFieldColumn { .. }
337 | NoFieldColumn { .. }
338 | AddingFieldColumn { .. }
339 | ParseRegionOptions { .. }
340 | UnexpectedRequest { .. }
341 | UnsupportedAlterKind { .. }
342 | UnsupportedRemapManifestsRequest { .. } => StatusCode::InvalidArguments,
343
344 ForbiddenPhysicalAlter { .. } | UnsupportedRegionRequest { .. } => {
345 StatusCode::Unsupported
346 }
347
348 DeserializeColumnMetadata { .. }
349 | SerializeColumnMetadata { .. }
350 | DecodeColumnValue { .. }
351 | ParseRegionId { .. }
352 | InvalidMetadata { .. }
353 | SetSkippingIndexOption { .. }
354 | SerializeRegionManifestInfo { .. }
355 | NoOpenRegionResult { .. } => StatusCode::Unexpected,
356
357 PhysicalRegionNotFound { .. } | LogicalRegionNotFound { .. } => {
358 StatusCode::RegionNotFound
359 }
360
361 ColumnNotFound { .. } => StatusCode::TableColumnNotFound,
362
363 CreateMitoRegion { source, .. }
364 | OpenMitoRegion { source, .. }
365 | CloseMitoRegion { source, .. }
366 | MitoReadOperation { source, .. }
367 | MitoWriteOperation { source, .. }
368 | MitoFlushOperation { source, .. }
369 | MitoSyncOperation { source, .. }
370 | MitoEnterStagingOperation { source, .. }
371 | BatchOpenMitoRegion { source, .. }
372 | BatchCatchupMitoRegion { source, .. } => source.status_code(),
373
374 EncodePrimaryKey { source, .. } => source.status_code(),
375
376 CollectRecordBatchStream { source, .. } => source.status_code(),
377
378 StartRepeatedTask { source, .. } => source.status_code(),
379
380 MetricManifestInfo { .. } => StatusCode::Internal,
381
382 CacheGet { source, .. } => source.status_code(),
383 }
384 }
385
386 fn as_any(&self) -> &dyn Any {
387 self
388 }
389}