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::{FileId, 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(
132 "Mito copy region from operation fails, source region id: {}, target region id: {}",
133 source_region_id,
134 target_region_id
135 ))]
136 MitoCopyRegionFromOperation {
137 source: BoxedError,
138 #[snafu(implicit)]
139 location: Location,
140 source_region_id: RegionId,
141 target_region_id: RegionId,
142 },
143
144 #[snafu(display("Mito edit region operation fails, region id: {}", region_id))]
145 MitoEditRegion {
146 region_id: RegionId,
147 source: BoxedError,
148 #[snafu(implicit)]
149 location: Location,
150 },
151
152 #[snafu(display("Failed to encode primary key"))]
153 EncodePrimaryKey {
154 source: mito_codec::error::Error,
155 #[snafu(implicit)]
156 location: Location,
157 },
158
159 #[snafu(display("Mito write operation fails"))]
160 MitoWriteOperation {
161 source: BoxedError,
162 #[snafu(implicit)]
163 location: Location,
164 },
165
166 #[snafu(display("Mito flush operation fails"))]
167 MitoFlushOperation {
168 source: BoxedError,
169 #[snafu(implicit)]
170 location: Location,
171 },
172
173 #[snafu(display("Mito sync operation fails"))]
174 MitoSyncOperation {
175 source: BoxedError,
176 #[snafu(implicit)]
177 location: Location,
178 },
179
180 #[snafu(display("Mito enter staging operation fails"))]
181 MitoEnterStagingOperation {
182 source: BoxedError,
183 #[snafu(implicit)]
184 location: Location,
185 },
186
187 #[snafu(display("Failed to collect record batch stream"))]
188 CollectRecordBatchStream {
189 source: common_recordbatch::error::Error,
190 #[snafu(implicit)]
191 location: Location,
192 },
193
194 #[snafu(display("Internal column {} is reserved", column))]
195 InternalColumnOccupied {
196 column: String,
197 #[snafu(implicit)]
198 location: Location,
199 },
200
201 #[snafu(display("Required table option is missing"))]
202 MissingRegionOption {
203 #[snafu(implicit)]
204 location: Location,
205 },
206
207 #[snafu(display("Region options are conflicted"))]
208 ConflictRegionOption {
209 #[snafu(implicit)]
210 location: Location,
211 },
212
213 #[snafu(display("Physical region {} not found", region_id))]
214 PhysicalRegionNotFound {
215 region_id: RegionId,
216 #[snafu(implicit)]
217 location: Location,
218 },
219
220 #[snafu(display("Logical region {} not found", region_id))]
221 LogicalRegionNotFound {
222 region_id: RegionId,
223 #[snafu(implicit)]
224 location: Location,
225 },
226
227 #[snafu(display("Column type mismatch. Expect {:?}, got {:?}", expect, actual))]
228 ColumnTypeMismatch {
229 expect: ConcreteDataType,
230 actual: ConcreteDataType,
231 #[snafu(implicit)]
232 location: Location,
233 },
234
235 #[snafu(display("Column {} not found in logical region {}", name, region_id))]
236 ColumnNotFound {
237 name: String,
238 region_id: RegionId,
239 #[snafu(implicit)]
240 location: Location,
241 },
242
243 #[snafu(display("Table id count mismatch. Expect {}, got {}", expected, actual))]
244 TableIdCountMismatch {
245 expected: usize,
246 actual: usize,
247 #[snafu(implicit)]
248 location: Location,
249 },
250
251 #[snafu(display("Alter request to physical region is forbidden"))]
252 ForbiddenPhysicalAlter {
253 #[snafu(implicit)]
254 location: Location,
255 },
256
257 #[snafu(display("Write request to physical region is forbidden"))]
258 ForbiddenPhysicalWrite {
259 #[snafu(implicit)]
260 location: Location,
261 },
262
263 #[snafu(display("Invalid region metadata"))]
264 InvalidMetadata {
265 source: store_api::metadata::MetadataError,
266 #[snafu(implicit)]
267 location: Location,
268 },
269
270 #[snafu(display("Invalid request for region {}, reason: {}", region_id, reason))]
271 InvalidRequest {
272 reason: String,
273 region_id: RegionId,
274 #[snafu(implicit)]
275 location: Location,
276 },
277
278 #[snafu(display(
279 "Physical region {} is busy, there are still some logical regions using it",
280 region_id
281 ))]
282 PhysicalRegionBusy {
283 region_id: RegionId,
284 #[snafu(implicit)]
285 location: Location,
286 },
287
288 #[snafu(display("Unsupported region request: {}", request))]
289 UnsupportedRegionRequest {
290 request: Box<RegionRequest>,
291 #[snafu(implicit)]
292 location: Location,
293 },
294
295 #[snafu(display("Unsupported remap manifests request for region {}", region_id))]
296 UnsupportedRemapManifestsRequest {
297 region_id: RegionId,
298 #[snafu(implicit)]
299 location: Location,
300 },
301
302 #[snafu(display("Unsupported sync region from request for region {}", region_id))]
303 UnsupportedSyncRegionFromRequest {
304 region_id: RegionId,
305 #[snafu(implicit)]
306 location: Location,
307 },
308
309 #[snafu(display("Missing file metas in region {}, file ids: {:?}", region_id, file_ids))]
310 MissingFiles {
311 region_id: RegionId,
312 #[snafu(implicit)]
313 location: Location,
314 file_ids: Vec<FileId>,
315 },
316
317 #[snafu(display("Unsupported alter kind: {}", kind))]
318 UnsupportedAlterKind {
319 kind: String,
320 #[snafu(implicit)]
321 location: Location,
322 },
323
324 #[snafu(display("Multiple field column found: {} and {}", previous, current))]
325 MultipleFieldColumn {
326 previous: String,
327 current: String,
328 #[snafu(implicit)]
329 location: Location,
330 },
331
332 #[snafu(display("Adding field column {} to physical table", name))]
333 AddingFieldColumn {
334 name: String,
335 #[snafu(implicit)]
336 location: Location,
337 },
338
339 #[snafu(display("No field column found"))]
340 NoFieldColumn {
341 #[snafu(implicit)]
342 location: Location,
343 },
344
345 #[snafu(display("Failed to set SKIPPING index option"))]
346 SetSkippingIndexOption {
347 source: datatypes::error::Error,
348 #[snafu(implicit)]
349 location: Location,
350 },
351
352 #[snafu(display(
353 "Failed to create default value for column {} of region {}",
354 column,
355 region_id
356 ))]
357 CreateDefault {
358 region_id: RegionId,
359 column: String,
360 source: datatypes::error::Error,
361 #[snafu(implicit)]
362 location: Location,
363 },
364
365 #[snafu(display("Unexpected request: {}", reason))]
366 UnexpectedRequest {
367 reason: String,
368 #[snafu(implicit)]
369 location: Location,
370 },
371
372 #[snafu(display("Expected metric manifest info, region: {}", region_id))]
373 MetricManifestInfo {
374 region_id: RegionId,
375 #[snafu(implicit)]
376 location: Location,
377 },
378
379 #[snafu(display("Failed to start repeated task: {}", name))]
380 StartRepeatedTask {
381 name: String,
382 source: common_runtime::error::Error,
383 #[snafu(implicit)]
384 location: Location,
385 },
386
387 #[snafu(display("Get value from cache"))]
388 CacheGet {
389 source: Arc<Error>,
390 #[snafu(implicit)]
391 location: Location,
392 },
393}
394
395pub type Result<T, E = Error> = std::result::Result<T, E>;
396
397impl ErrorExt for Error {
398 fn status_code(&self) -> StatusCode {
399 use Error::*;
400
401 match self {
402 InternalColumnOccupied { .. }
403 | MissingRegionOption { .. }
404 | ConflictRegionOption { .. }
405 | ColumnTypeMismatch { .. }
406 | TableIdCountMismatch { .. }
407 | PhysicalRegionBusy { .. }
408 | MultipleFieldColumn { .. }
409 | NoFieldColumn { .. }
410 | AddingFieldColumn { .. }
411 | ParseRegionOptions { .. }
412 | UnexpectedRequest { .. }
413 | UnsupportedAlterKind { .. }
414 | UnsupportedRemapManifestsRequest { .. }
415 | UnsupportedSyncRegionFromRequest { .. }
416 | InvalidRequest { .. }
417 | CreateDefault { .. } => StatusCode::InvalidArguments,
418
419 ForbiddenPhysicalAlter { .. }
420 | ForbiddenPhysicalWrite { .. }
421 | UnsupportedRegionRequest { .. }
422 | MissingFiles { .. } => StatusCode::Unsupported,
423
424 DeserializeColumnMetadata { .. }
425 | SerializeColumnMetadata { .. }
426 | DecodeColumnValue { .. }
427 | ParseRegionId { .. }
428 | InvalidMetadata { .. }
429 | SetSkippingIndexOption { .. }
430 | SerializeRegionManifestInfo { .. }
431 | NoOpenRegionResult { .. } => StatusCode::Unexpected,
432
433 PhysicalRegionNotFound { .. } | LogicalRegionNotFound { .. } => {
434 StatusCode::RegionNotFound
435 }
436
437 ColumnNotFound { .. } => StatusCode::TableColumnNotFound,
438
439 CreateMitoRegion { source, .. }
440 | OpenMitoRegion { source, .. }
441 | CloseMitoRegion { source, .. }
442 | MitoReadOperation { source, .. }
443 | MitoWriteOperation { source, .. }
444 | MitoFlushOperation { source, .. }
445 | MitoSyncOperation { source, .. }
446 | MitoEnterStagingOperation { source, .. }
447 | BatchOpenMitoRegion { source, .. }
448 | BatchCatchupMitoRegion { source, .. }
449 | MitoCopyRegionFromOperation { source, .. }
450 | MitoEditRegion { source, .. } => source.status_code(),
451
452 EncodePrimaryKey { source, .. } => source.status_code(),
453
454 CollectRecordBatchStream { source, .. } => source.status_code(),
455
456 StartRepeatedTask { source, .. } => source.status_code(),
457
458 MetricManifestInfo { .. } => StatusCode::Internal,
459
460 CacheGet { source, .. } => source.status_code(),
461 }
462 }
463
464 fn as_any(&self) -> &dyn Any {
465 self
466 }
467}