1use std::any::Any;
16use std::sync::Arc;
17
18use common_datasource::compression::CompressionType;
19use common_error::ext::{BoxedError, ErrorExt, RetryHint};
20use common_error::status_code::StatusCode;
21use common_macro::stack_trace_debug;
22use common_memory_manager;
23use common_runtime::JoinError;
24use common_time::Timestamp;
25use common_time::timestamp::TimeUnit;
26use datatypes::arrow::error::ArrowError;
27use datatypes::prelude::ConcreteDataType;
28use object_store::ErrorKind;
29use object_store::error::retry_hint_from_opendal_error;
30use partition::error::Error as PartitionError;
31use prost::DecodeError;
32use snafu::{Location, Snafu};
33use store_api::ManifestVersion;
34use store_api::logstore::provider::Provider;
35use store_api::storage::{FileId, RegionId};
36use tokio::time::error::Elapsed;
37
38use crate::cache::file_cache::FileType;
39use crate::region::RegionRoleState;
40use crate::schedule::remote_job_scheduler::JobId;
41use crate::worker::WorkerId;
42
43#[derive(Snafu)]
44#[snafu(visibility(pub))]
45#[stack_trace_debug]
46pub enum Error {
47 #[snafu(display("Unexpected data type"))]
48 DataTypeMismatch {
49 source: datatypes::error::Error,
50 #[snafu(implicit)]
51 location: Location,
52 },
53
54 #[snafu(display("External error, context: {}", context))]
55 External {
56 source: BoxedError,
57 context: String,
58 #[snafu(implicit)]
59 location: Location,
60 },
61
62 #[snafu(display("OpenDAL operator failed"))]
63 OpenDal {
64 #[snafu(implicit)]
65 location: Location,
66 #[snafu(source)]
67 error: object_store::Error,
68 },
69
70 #[snafu(display(
71 "Manifest delta {} disappeared after it was listed, path: {}",
72 version,
73 path
74 ))]
75 ManifestDeltaNotFound {
76 version: ManifestVersion,
77 path: String,
78 #[snafu(source)]
79 error: object_store::Error,
80 #[snafu(implicit)]
81 location: Location,
82 },
83
84 #[snafu(display("Fail to compress object by {}, path: {}", compress_type, path))]
85 CompressObject {
86 compress_type: CompressionType,
87 path: String,
88 #[snafu(source)]
89 error: std::io::Error,
90 },
91
92 #[snafu(display("Fail to decompress object by {}, path: {}", compress_type, path))]
93 DecompressObject {
94 compress_type: CompressionType,
95 path: String,
96 #[snafu(source)]
97 error: std::io::Error,
98 },
99
100 #[snafu(display("Failed to ser/de json object"))]
101 SerdeJson {
102 #[snafu(implicit)]
103 location: Location,
104 #[snafu(source)]
105 error: serde_json::Error,
106 },
107
108 #[snafu(display("Failed to serialize column metadata"))]
109 SerializeColumnMetadata {
110 #[snafu(source)]
111 error: serde_json::Error,
112 #[snafu(implicit)]
113 location: Location,
114 },
115
116 #[snafu(display("Failed to serialize manifest, region_id: {}", region_id))]
117 SerializeManifest {
118 region_id: RegionId,
119 #[snafu(source)]
120 error: serde_json::Error,
121 #[snafu(implicit)]
122 location: Location,
123 },
124
125 #[snafu(display("Invalid scan index, start: {}, end: {}", start, end))]
126 InvalidScanIndex {
127 start: ManifestVersion,
128 end: ManifestVersion,
129 #[snafu(implicit)]
130 location: Location,
131 },
132
133 #[snafu(display("Invalid UTF-8 content"))]
134 Utf8 {
135 #[snafu(implicit)]
136 location: Location,
137 #[snafu(source)]
138 error: std::str::Utf8Error,
139 },
140
141 #[snafu(display("Cannot find RegionMetadata"))]
142 RegionMetadataNotFound {
143 #[snafu(implicit)]
144 location: Location,
145 },
146
147 #[snafu(display("Failed to join handle"))]
148 Join {
149 #[snafu(source)]
150 error: common_runtime::JoinError,
151 #[snafu(implicit)]
152 location: Location,
153 },
154
155 #[snafu(display("Worker {} is stopped", id))]
156 WorkerStopped {
157 id: WorkerId,
158 #[snafu(implicit)]
159 location: Location,
160 },
161
162 #[snafu(display("Failed to recv result"))]
163 Recv {
164 #[snafu(source)]
165 error: tokio::sync::oneshot::error::RecvError,
166 #[snafu(implicit)]
167 location: Location,
168 },
169
170 #[snafu(display("Invalid metadata, {}", reason))]
171 InvalidMeta {
172 reason: String,
173 #[snafu(implicit)]
174 location: Location,
175 },
176
177 #[snafu(display("Invalid region metadata"))]
178 InvalidMetadata {
179 source: store_api::metadata::MetadataError,
180 #[snafu(implicit)]
181 location: Location,
182 },
183
184 #[snafu(display("Failed to create RecordBatch from vectors"))]
185 NewRecordBatch {
186 #[snafu(implicit)]
187 location: Location,
188 #[snafu(source)]
189 error: ArrowError,
190 },
191
192 #[snafu(display("Failed to read parquet file, path: {}", path))]
193 ReadParquet {
194 path: String,
195 #[snafu(source)]
196 error: parquet::errors::ParquetError,
197 #[snafu(implicit)]
198 location: Location,
199 },
200
201 #[snafu(display("Failed to load range result"))]
202 LoadRangeResult {
203 source: Arc<Error>,
204 #[snafu(implicit)]
205 location: Location,
206 },
207
208 #[snafu(display("Failed to load SST metadata"))]
209 LoadSstMeta {
210 source: Arc<Error>,
211 #[snafu(implicit)]
212 location: Location,
213 },
214
215 #[snafu(display("Failed to load Parquet page"))]
216 LoadParquetPage {
217 source: Arc<Error>,
218 #[snafu(implicit)]
219 location: Location,
220 },
221
222 #[snafu(display("Failed to write parquet file"))]
223 WriteParquet {
224 #[snafu(source)]
225 error: parquet::errors::ParquetError,
226 #[snafu(implicit)]
227 location: Location,
228 },
229
230 #[snafu(display(
231 "Cannot assign a stable field id to native histogram sub-field '{}' of column id {} (unknown sub-field name or derived id overflows i32)",
232 field_name,
233 column_id
234 ))]
235 InvalidNativeHistogramSubfield {
236 column_id: i32,
237 field_name: String,
238 #[snafu(implicit)]
239 location: Location,
240 },
241
242 #[snafu(display(
243 "Native histogram column '{}' has no usable PARQUET:field_id to namespace its sub-field ids (missing, malformed, or exceeds i32::MAX)",
244 field_name
245 ))]
246 InvalidNativeHistogramFieldId {
247 field_name: String,
248 #[snafu(implicit)]
249 location: Location,
250 },
251
252 #[snafu(display("Region {} not found", region_id))]
253 RegionNotFound {
254 region_id: RegionId,
255 #[snafu(implicit)]
256 location: Location,
257 },
258
259 #[snafu(display("Object store not found: {}", object_store))]
260 ObjectStoreNotFound {
261 object_store: String,
262 #[snafu(implicit)]
263 location: Location,
264 },
265
266 #[snafu(display("Region {} is corrupted, reason: {}", region_id, reason))]
267 RegionCorrupted {
268 region_id: RegionId,
269 reason: String,
270 #[snafu(implicit)]
271 location: Location,
272 },
273
274 #[snafu(display("Invalid request to region {}, reason: {}", region_id, reason))]
275 InvalidRequest {
276 region_id: RegionId,
277 reason: String,
278 #[snafu(implicit)]
279 location: Location,
280 },
281
282 #[snafu(display(
283 "STALE_CURSOR: incremental query stale, region: {}, given_seq: {}, min_readable_seq: {}, retry_hint: FALLBACK_FULL_RECOMPUTE",
284 region_id,
285 given_seq,
286 min_readable_seq
287 ))]
288 IncrementalQueryStale {
289 region_id: RegionId,
290 given_seq: u64,
291 min_readable_seq: u64,
292 #[snafu(implicit)]
293 location: Location,
294 },
295
296 #[snafu(display(
297 "STALE_SNAPSHOT_FENCE: snapshot upper bound stale, region: {}, given_seq: {}, min_enforceable_seq: {}, retry_hint: REBIND_SNAPSHOT_FENCE",
298 region_id,
299 given_seq,
300 min_enforceable_seq
301 ))]
302 SnapshotFenceStale {
303 region_id: RegionId,
304 given_seq: u64,
305 min_enforceable_seq: u64,
306 #[snafu(implicit)]
307 location: Location,
308 },
309
310 #[snafu(display(
311 "SEQUENCE_RANGE_UNSUPPORTED: exact sequence-range read unsupported, region: {}, min_seq: {}, max_seq: {}, reason: {}, retry_hint: FALLBACK_MEMTABLE_ONLY_OR_FULL_RECOMPUTE",
312 region_id,
313 min_seq,
314 max_seq,
315 reason
316 ))]
317 SequenceRangeUnsupported {
318 region_id: RegionId,
319 min_seq: u64,
320 max_seq: u64,
321 reason: String,
322 #[snafu(implicit)]
323 location: Location,
324 },
325
326 #[snafu(display(
327 "region {} is unusable for sequence reads: file {} declares region {}",
328 region_id,
329 file_id,
330 file_region_id
331 ))]
332 RegionSequenceDomainBroken {
333 region_id: RegionId,
334 file_region_id: RegionId,
335 file_id: FileId,
336 #[snafu(implicit)]
337 location: Location,
338 },
339
340 #[snafu(display("Old manifest missing for region {}", region_id))]
341 MissingOldManifest {
342 region_id: RegionId,
343 #[snafu(implicit)]
344 location: Location,
345 },
346
347 #[snafu(display("New manifest missing for region {}", region_id))]
348 MissingNewManifest {
349 region_id: RegionId,
350 #[snafu(implicit)]
351 location: Location,
352 },
353
354 #[snafu(display("Manifest missing for region {}", region_id))]
355 MissingManifest {
356 region_id: RegionId,
357 #[snafu(implicit)]
358 location: Location,
359 },
360
361 #[snafu(display("File consistency check failed for file {}: {}", file_id, reason))]
362 InconsistentFile {
363 file_id: FileId,
364 reason: String,
365 #[snafu(implicit)]
366 location: Location,
367 },
368
369 #[snafu(display("Files lost during remapping: old={}, new={}", old_count, new_count))]
370 FilesLost {
371 old_count: usize,
372 new_count: usize,
373 #[snafu(implicit)]
374 location: Location,
375 },
376
377 #[snafu(display("No old manifests provided (need at least one for template)"))]
378 NoOldManifests {
379 #[snafu(implicit)]
380 location: Location,
381 },
382
383 #[snafu(display("Failed to fetch manifests"))]
384 FetchManifests {
385 #[snafu(implicit)]
386 location: Location,
387 source: BoxedError,
388 },
389
390 #[snafu(display("Partition expression missing for region {}", region_id))]
391 MissingPartitionExpr {
392 region_id: RegionId,
393 #[snafu(implicit)]
394 location: Location,
395 },
396
397 #[snafu(display("Failed to serialize partition expression: {}", source))]
398 SerializePartitionExpr {
399 #[snafu(source)]
400 source: PartitionError,
401 #[snafu(implicit)]
402 location: Location,
403 },
404
405 #[snafu(display(
406 "Failed to convert ConcreteDataType to ColumnDataType, reason: {}",
407 reason
408 ))]
409 ConvertColumnDataType {
410 reason: String,
411 source: api::error::Error,
412 #[snafu(implicit)]
413 location: Location,
414 },
415
416 #[snafu(display("Need to fill default value for region {}", region_id))]
419 FillDefault {
420 region_id: RegionId,
421 },
423
424 #[snafu(display(
425 "Failed to create default value for column {} of region {}",
426 column,
427 region_id
428 ))]
429 CreateDefault {
430 region_id: RegionId,
431 column: String,
432 source: datatypes::Error,
433 #[snafu(implicit)]
434 location: Location,
435 },
436
437 #[snafu(display("Failed to build entry, region_id: {}", region_id))]
438 BuildEntry {
439 region_id: RegionId,
440 #[snafu(implicit)]
441 location: Location,
442 source: BoxedError,
443 },
444
445 #[snafu(display("Failed to write WAL"))]
446 WriteWal {
447 #[snafu(implicit)]
448 location: Location,
449 source: BoxedError,
450 },
451
452 #[snafu(display("Failed to read WAL, provider: {}", provider))]
453 ReadWal {
454 provider: Provider,
455 #[snafu(implicit)]
456 location: Location,
457 source: BoxedError,
458 },
459
460 #[snafu(display("Failed to decode WAL entry, region_id: {}", region_id))]
461 DecodeWal {
462 region_id: RegionId,
463 #[snafu(implicit)]
464 location: Location,
465 #[snafu(source)]
466 error: DecodeError,
467 },
468
469 #[snafu(display("Failed to delete WAL, region_id: {}", region_id))]
470 DeleteWal {
471 region_id: RegionId,
472 #[snafu(implicit)]
473 location: Location,
474 source: BoxedError,
475 },
476
477 #[snafu(display("Failed to wait for the WAL to be durable, region_id: {}", region_id))]
478 WaitWalDurable {
479 region_id: RegionId,
480 #[snafu(implicit)]
481 location: Location,
482 source: BoxedError,
483 },
484
485 #[snafu(display("Failed to check the WAL history, region_id: {}", region_id))]
486 CheckWalHistory {
487 region_id: RegionId,
488 #[snafu(implicit)]
489 location: Location,
490 source: BoxedError,
491 },
492
493 #[snafu(display("Failed to write region"))]
495 WriteGroup { source: Arc<Error> },
496
497 #[snafu(display("Invalid parquet SST file {}, reason: {}", file, reason))]
498 InvalidParquet {
499 file: String,
500 reason: String,
501 #[snafu(implicit)]
502 location: Location,
503 },
504
505 #[snafu(display("Invalid batch, {}", reason))]
506 InvalidBatch {
507 reason: String,
508 #[snafu(implicit)]
509 location: Location,
510 },
511
512 #[snafu(display("Invalid arrow record batch, {}", reason))]
513 InvalidRecordBatch {
514 reason: String,
515 #[snafu(implicit)]
516 location: Location,
517 },
518
519 #[snafu(display("Invalid wal read request, {}", reason))]
520 InvalidWalReadRequest {
521 reason: String,
522 #[snafu(implicit)]
523 location: Location,
524 },
525
526 #[snafu(display("Failed to convert array to vector"))]
527 ConvertVector {
528 #[snafu(implicit)]
529 location: Location,
530 source: datatypes::error::Error,
531 },
532
533 #[snafu(display("Failed to compute arrow arrays"))]
534 ComputeArrow {
535 #[snafu(implicit)]
536 location: Location,
537 #[snafu(source)]
538 error: datatypes::arrow::error::ArrowError,
539 },
540
541 #[snafu(display("Failed to evaluate partition filter"))]
542 EvalPartitionFilter {
543 #[snafu(implicit)]
544 location: Location,
545 #[snafu(source)]
546 error: datafusion::error::DataFusionError,
547 },
548
549 #[snafu(display("Failed to merge candidate series"))]
550 MergeCandidateSeries {
551 #[snafu(implicit)]
552 location: Location,
553 #[snafu(source)]
554 error: datafusion::error::DataFusionError,
555 },
556
557 #[snafu(display("Failed to compute vector"))]
558 ComputeVector {
559 #[snafu(implicit)]
560 location: Location,
561 source: datatypes::error::Error,
562 },
563
564 #[snafu(display("Primary key length mismatch, expect: {}, actual: {}", expect, actual))]
565 PrimaryKeyLengthMismatch {
566 expect: usize,
567 actual: usize,
568 #[snafu(implicit)]
569 location: Location,
570 },
571
572 #[snafu(display("Invalid sender",))]
573 InvalidSender {
574 #[snafu(implicit)]
575 location: Location,
576 },
577
578 #[snafu(display("Invalid scheduler state"))]
579 InvalidSchedulerState {
580 #[snafu(implicit)]
581 location: Location,
582 },
583
584 #[snafu(display("Failed to stop scheduler"))]
585 StopScheduler {
586 #[snafu(source)]
587 error: JoinError,
588 #[snafu(implicit)]
589 location: Location,
590 },
591
592 #[snafu(display(
593 "Failed to batch delete SST files, region id: {}, file ids: {:?}",
594 region_id,
595 file_ids
596 ))]
597 DeleteSsts {
598 region_id: RegionId,
599 file_ids: Vec<FileId>,
600 #[snafu(source)]
601 error: object_store::Error,
602 #[snafu(implicit)]
603 location: Location,
604 },
605
606 #[snafu(display("Failed to delete index file, file id: {}", file_id))]
607 DeleteIndex {
608 file_id: FileId,
609 #[snafu(source)]
610 error: object_store::Error,
611 #[snafu(implicit)]
612 location: Location,
613 },
614
615 #[snafu(display("Failed to batch delete index files, file ids: {:?}", file_ids))]
616 DeleteIndexes {
617 file_ids: Vec<FileId>,
618 #[snafu(source)]
619 error: object_store::Error,
620 #[snafu(implicit)]
621 location: Location,
622 },
623
624 #[snafu(display("Failed to flush region {}", region_id))]
625 FlushRegion {
626 region_id: RegionId,
627 source: Arc<Error>,
628 #[snafu(implicit)]
629 location: Location,
630 },
631
632 #[snafu(display("Region {} is dropped", region_id))]
633 RegionDropped {
634 region_id: RegionId,
635 #[snafu(implicit)]
636 location: Location,
637 },
638
639 #[snafu(display("Region {} is closed", region_id))]
640 RegionClosed {
641 region_id: RegionId,
642 #[snafu(implicit)]
643 location: Location,
644 },
645
646 #[snafu(display(
647 "Stale compaction execution for region {}, the region may have been reopened, truncated or the compaction was superseded",
648 region_id
649 ))]
650 StaleCompactionExecution {
651 region_id: RegionId,
652 #[snafu(implicit)]
653 location: Location,
654 },
655
656 #[snafu(display("Region {} is truncated", region_id))]
657 RegionTruncated {
658 region_id: RegionId,
659 #[snafu(implicit)]
660 location: Location,
661 },
662
663 #[snafu(display(
664 "Engine write buffer is full, rejecting write requests of region {}",
665 region_id,
666 ))]
667 RejectWrite {
668 region_id: RegionId,
669 #[snafu(implicit)]
670 location: Location,
671 },
672
673 #[snafu(display("Region {} rejects writes while in staging", region_id))]
674 RejectWriteInStaging {
675 region_id: RegionId,
676 #[snafu(implicit)]
677 location: Location,
678 },
679
680 #[snafu(display("Region {} does not hold a valid leader lease", region_id))]
681 RegionLeaseExpired {
682 region_id: RegionId,
683 #[snafu(implicit)]
684 location: Location,
685 },
686
687 #[snafu(display(
688 "Region {} lost its leader lease while writing to the WAL, the write may have been applied",
689 region_id
690 ))]
691 UnacknowledgedWrite {
692 region_id: RegionId,
693 #[snafu(implicit)]
694 location: Location,
695 },
696
697 #[snafu(display("Failed to compact region {}", region_id))]
698 CompactRegion {
699 region_id: RegionId,
700 source: Arc<Error>,
701 #[snafu(implicit)]
702 location: Location,
703 },
704
705 #[snafu(display("Failed to edit region {}", region_id))]
706 EditRegion {
707 region_id: RegionId,
708 source: Arc<Error>,
709 #[snafu(implicit)]
710 location: Location,
711 },
712
713 #[snafu(display(
714 "Failed to compat readers for region {}, reason: {}",
715 region_id,
716 reason,
717 ))]
718 CompatReader {
719 region_id: RegionId,
720 reason: String,
721 #[snafu(implicit)]
722 location: Location,
723 },
724
725 #[snafu(display("Invalue region req"))]
726 InvalidRegionRequest {
727 source: store_api::metadata::MetadataError,
728 #[snafu(implicit)]
729 location: Location,
730 },
731
732 #[snafu(display(
733 "Region {} is in {:?} state, which does not permit manifest updates.",
734 region_id,
735 state
736 ))]
737 UpdateManifest {
738 region_id: RegionId,
739 state: RegionRoleState,
740 #[snafu(implicit)]
741 location: Location,
742 },
743
744 #[snafu(display("Region {} is in {:?} state, expect: {:?}", region_id, state, expect))]
745 RegionState {
746 region_id: RegionId,
747 state: RegionRoleState,
748 expect: RegionRoleState,
749 #[snafu(implicit)]
750 location: Location,
751 },
752
753 #[snafu(display(
754 "Partition expr version mismatch for region {}: request {}, expected {}",
755 region_id,
756 request_version,
757 expected_version
758 ))]
759 PartitionExprVersionMismatch {
760 region_id: RegionId,
761 request_version: u64,
762 expected_version: u64,
763 #[snafu(implicit)]
764 location: Location,
765 },
766
767 #[snafu(display("Invalid options"))]
768 JsonOptions {
769 #[snafu(source)]
770 error: serde_json::Error,
771 #[snafu(implicit)]
772 location: Location,
773 },
774
775 #[snafu(display(
776 "Empty region directory, region_id: {}, region_dir: {}",
777 region_id,
778 region_dir,
779 ))]
780 EmptyRegionDir {
781 region_id: RegionId,
782 region_dir: String,
783 #[snafu(implicit)]
784 location: Location,
785 },
786
787 #[snafu(display("Empty manifest directory, manifest_dir: {}", manifest_dir,))]
788 EmptyManifestDir {
789 manifest_dir: String,
790 #[snafu(implicit)]
791 location: Location,
792 },
793
794 #[snafu(display("Column not found, column: {column}"))]
795 ColumnNotFound {
796 column: String,
797 #[snafu(implicit)]
798 location: Location,
799 },
800
801 #[snafu(display("Failed to build index applier"))]
802 BuildIndexApplier {
803 source: index::inverted_index::error::Error,
804 #[snafu(implicit)]
805 location: Location,
806 },
807
808 #[snafu(display("Failed to build index asynchronously in region {}", region_id))]
809 BuildIndexAsync {
810 region_id: RegionId,
811 source: Arc<Error>,
812 #[snafu(implicit)]
813 location: Location,
814 },
815
816 #[snafu(display(
817 "Index build did not complete for files {:?} in region {}",
818 file_ids,
819 region_id
820 ))]
821 IndexBuildIncomplete {
822 region_id: RegionId,
823 file_ids: Vec<FileId>,
824 #[snafu(implicit)]
825 location: Location,
826 },
827
828 #[snafu(display("Failed to convert value"))]
829 ConvertValue {
830 source: datatypes::error::Error,
831 #[snafu(implicit)]
832 location: Location,
833 },
834
835 #[snafu(display("Failed to apply inverted index"))]
836 ApplyInvertedIndex {
837 source: index::inverted_index::error::Error,
838 #[snafu(implicit)]
839 location: Location,
840 },
841
842 #[snafu(display("Failed to apply bloom filter index"))]
843 ApplyBloomFilterIndex {
844 source: index::bloom_filter::error::Error,
845 #[snafu(implicit)]
846 location: Location,
847 },
848
849 #[snafu(display("Failed to push index value"))]
850 PushIndexValue {
851 source: index::inverted_index::error::Error,
852 #[snafu(implicit)]
853 location: Location,
854 },
855
856 #[snafu(display("Failed to write index completely"))]
857 IndexFinish {
858 source: index::inverted_index::error::Error,
859 #[snafu(implicit)]
860 location: Location,
861 },
862
863 #[snafu(display("Operate on aborted index"))]
864 OperateAbortedIndex {
865 #[snafu(implicit)]
866 location: Location,
867 },
868
869 #[snafu(display("Failed to read puffin blob"))]
870 PuffinReadBlob {
871 source: puffin::error::Error,
872 #[snafu(implicit)]
873 location: Location,
874 },
875
876 #[snafu(display("Failed to add blob to puffin file"))]
877 PuffinAddBlob {
878 source: puffin::error::Error,
879 #[snafu(implicit)]
880 location: Location,
881 },
882
883 #[snafu(display("Failed to clean dir {dir}"))]
884 CleanDir {
885 dir: String,
886 #[snafu(source)]
887 error: std::io::Error,
888 #[snafu(implicit)]
889 location: Location,
890 },
891
892 #[snafu(display("Invalid config, {reason}"))]
893 InvalidConfig {
894 reason: String,
895 #[snafu(implicit)]
896 location: Location,
897 },
898
899 #[snafu(display(
900 "Stale log entry found during replay, region: {}, flushed: {}, replayed: {}",
901 region_id,
902 flushed_entry_id,
903 unexpected_entry_id
904 ))]
905 StaleLogEntry {
906 region_id: RegionId,
907 flushed_entry_id: u64,
908 unexpected_entry_id: u64,
909 },
910
911 #[snafu(display(
912 "Failed to download file, region_id: {}, file_id: {}, file_type: {:?}",
913 region_id,
914 file_id,
915 file_type,
916 ))]
917 Download {
918 region_id: RegionId,
919 file_id: FileId,
920 file_type: FileType,
921 #[snafu(source)]
922 error: std::io::Error,
923 #[snafu(implicit)]
924 location: Location,
925 },
926
927 #[snafu(display(
928 "Failed to upload file, region_id: {}, file_id: {}, file_type: {:?}",
929 region_id,
930 file_id,
931 file_type,
932 ))]
933 Upload {
934 region_id: RegionId,
935 file_id: FileId,
936 file_type: FileType,
937 #[snafu(source)]
938 error: std::io::Error,
939 #[snafu(implicit)]
940 location: Location,
941 },
942
943 #[snafu(display("Failed to create directory {}", dir))]
944 CreateDir {
945 dir: String,
946 #[snafu(source)]
947 error: std::io::Error,
948 },
949
950 #[snafu(display("Record batch error"))]
951 RecordBatch {
952 source: common_recordbatch::error::Error,
953 #[snafu(implicit)]
954 location: Location,
955 },
956
957 #[snafu(display("BiErrors, first: {first}, second: {second}"))]
958 BiErrors {
959 first: Box<Error>,
960 second: Box<Error>,
961 #[snafu(implicit)]
962 location: Location,
963 },
964
965 #[snafu(display("Encode null value"))]
966 IndexEncodeNull {
967 #[snafu(implicit)]
968 location: Location,
969 },
970
971 #[snafu(display("Failed to encode memtable to Parquet bytes"))]
972 EncodeMemtable {
973 #[snafu(source)]
974 error: parquet::errors::ParquetError,
975 #[snafu(implicit)]
976 location: Location,
977 },
978
979 #[snafu(display("Partition {} out of range, {} in total", given, all))]
980 PartitionOutOfRange {
981 given: usize,
982 all: usize,
983 #[snafu(implicit)]
984 location: Location,
985 },
986
987 #[snafu(display("Failed to iter data part"))]
988 ReadDataPart {
989 #[snafu(implicit)]
990 location: Location,
991 #[snafu(source)]
992 error: parquet::errors::ParquetError,
993 },
994
995 #[snafu(display("Failed to read row group in memtable"))]
996 DecodeArrowRowGroup {
997 #[snafu(source)]
998 error: ArrowError,
999 #[snafu(implicit)]
1000 location: Location,
1001 },
1002
1003 #[snafu(display("Invalid region options, {}", reason))]
1004 InvalidRegionOptions {
1005 reason: String,
1006 #[snafu(implicit)]
1007 location: Location,
1008 },
1009
1010 #[snafu(display("checksum mismatch (actual: {}, expected: {})", actual, expected))]
1011 ChecksumMismatch { actual: u32, expected: u32 },
1012
1013 #[snafu(display(
1014 "No checkpoint found, region: {}, last_version: {}",
1015 region_id,
1016 last_version
1017 ))]
1018 NoCheckpoint {
1019 region_id: RegionId,
1020 last_version: ManifestVersion,
1021 #[snafu(implicit)]
1022 location: Location,
1023 },
1024
1025 #[snafu(display(
1026 "No manifests found in range: [{}..{}), region: {}, last_version: {}",
1027 start_version,
1028 end_version,
1029 region_id,
1030 last_version
1031 ))]
1032 NoManifests {
1033 region_id: RegionId,
1034 start_version: ManifestVersion,
1035 end_version: ManifestVersion,
1036 last_version: ManifestVersion,
1037 #[snafu(implicit)]
1038 location: Location,
1039 },
1040
1041 #[snafu(display(
1042 "Failed to install manifest to {}, region: {}, available manifest version: {}, last version: {}",
1043 target_version,
1044 region_id,
1045 available_version,
1046 last_version
1047 ))]
1048 InstallManifestTo {
1049 region_id: RegionId,
1050 target_version: ManifestVersion,
1051 available_version: ManifestVersion,
1052 #[snafu(implicit)]
1053 location: Location,
1054 last_version: ManifestVersion,
1055 },
1056
1057 #[snafu(display("Region {} is stopped", region_id))]
1058 RegionStopped {
1059 region_id: RegionId,
1060 #[snafu(implicit)]
1061 location: Location,
1062 },
1063
1064 #[snafu(display(
1065 "Time range predicate overflows, timestamp: {:?}, target unit: {}",
1066 timestamp,
1067 unit
1068 ))]
1069 TimeRangePredicateOverflow {
1070 timestamp: Timestamp,
1071 unit: TimeUnit,
1072 #[snafu(implicit)]
1073 location: Location,
1074 },
1075
1076 #[snafu(display("Failed to open region"))]
1077 OpenRegion {
1078 #[snafu(implicit)]
1079 location: Location,
1080 source: Arc<Error>,
1081 },
1082
1083 #[snafu(display(
1084 "Region {} does not satisfy requirement '{}': {}",
1085 region_id,
1086 requirement,
1087 reason
1088 ))]
1089 RegionRequirement {
1090 region_id: RegionId,
1091 requirement: &'static str,
1092 reason: &'static str,
1093 #[snafu(implicit)]
1094 location: Location,
1095 },
1096
1097 #[snafu(display("Failed to parse job id"))]
1098 ParseJobId {
1099 #[snafu(implicit)]
1100 location: Location,
1101 #[snafu(source)]
1102 error: uuid::Error,
1103 },
1104
1105 #[snafu(display("Operation is not supported: {}", err_msg))]
1106 UnsupportedOperation {
1107 err_msg: String,
1108 #[snafu(implicit)]
1109 location: Location,
1110 },
1111
1112 #[snafu(display(
1113 "Failed to remotely compact region {} by job {:?} due to {}",
1114 region_id,
1115 job_id,
1116 reason
1117 ))]
1118 RemoteCompaction {
1119 region_id: RegionId,
1120 job_id: Option<JobId>,
1121 reason: String,
1122 #[snafu(implicit)]
1123 location: Location,
1124 },
1125
1126 #[snafu(display("Failed to initialize puffin stager"))]
1127 PuffinInitStager {
1128 source: puffin::error::Error,
1129 #[snafu(implicit)]
1130 location: Location,
1131 },
1132
1133 #[snafu(display("Failed to purge puffin stager"))]
1134 PuffinPurgeStager {
1135 source: puffin::error::Error,
1136 #[snafu(implicit)]
1137 location: Location,
1138 },
1139
1140 #[snafu(display("Failed to build puffin reader"))]
1141 PuffinBuildReader {
1142 source: puffin::error::Error,
1143 #[snafu(implicit)]
1144 location: Location,
1145 },
1146
1147 #[snafu(display("Failed to retrieve index options from column metadata"))]
1148 IndexOptions {
1149 #[snafu(implicit)]
1150 location: Location,
1151 source: datatypes::error::Error,
1152 column_name: String,
1153 },
1154
1155 #[snafu(display("Failed to retrieve compression options of column {column_name}"))]
1156 CompressionOptions {
1157 #[snafu(implicit)]
1158 location: Location,
1159 source: datatypes::error::Error,
1160 column_name: String,
1161 },
1162
1163 #[snafu(display("Failed to create fulltext index creator"))]
1164 CreateFulltextCreator {
1165 source: index::fulltext_index::error::Error,
1166 #[snafu(implicit)]
1167 location: Location,
1168 },
1169
1170 #[snafu(display("Failed to cast vector of {from} to {to}"))]
1171 CastVector {
1172 #[snafu(implicit)]
1173 location: Location,
1174 from: ConcreteDataType,
1175 to: ConcreteDataType,
1176 source: datatypes::error::Error,
1177 },
1178
1179 #[snafu(display("Failed to push text to fulltext index"))]
1180 FulltextPushText {
1181 source: index::fulltext_index::error::Error,
1182 #[snafu(implicit)]
1183 location: Location,
1184 },
1185
1186 #[snafu(display("Failed to finalize fulltext index creator"))]
1187 FulltextFinish {
1188 source: index::fulltext_index::error::Error,
1189 #[snafu(implicit)]
1190 location: Location,
1191 },
1192
1193 #[snafu(display("Failed to apply fulltext index"))]
1194 ApplyFulltextIndex {
1195 source: index::fulltext_index::error::Error,
1196 #[snafu(implicit)]
1197 location: Location,
1198 },
1199
1200 #[snafu(display("SST file {} does not contain valid stats info", file_path))]
1201 StatsNotPresent {
1202 file_path: String,
1203 #[snafu(implicit)]
1204 location: Location,
1205 },
1206
1207 #[snafu(display("Failed to decode stats of file {}", file_path))]
1208 DecodeStats {
1209 file_path: String,
1210 #[snafu(implicit)]
1211 location: Location,
1212 },
1213
1214 #[snafu(display("Invalid SST primary key range: {reason}"))]
1215 InvalidPrimaryKeyRange {
1216 reason: String,
1217 #[snafu(implicit)]
1218 location: Location,
1219 },
1220
1221 #[snafu(display("Failed to decode SST primary key range {endpoint} endpoint"))]
1222 DecodePrimaryKeyRange {
1223 endpoint: &'static str,
1224 source: mito_codec::error::Error,
1225 #[snafu(implicit)]
1226 location: Location,
1227 },
1228
1229 #[snafu(display("Region {} is busy", region_id))]
1230 RegionBusy {
1231 region_id: RegionId,
1232 #[snafu(implicit)]
1233 location: Location,
1234 },
1235
1236 #[snafu(display("Failed to get schema metadata"))]
1237 GetSchemaMetadata {
1238 source: common_meta::error::Error,
1239 #[snafu(implicit)]
1240 location: Location,
1241 },
1242
1243 #[snafu(display("Timeout"))]
1244 Timeout {
1245 #[snafu(source)]
1246 error: Elapsed,
1247 #[snafu(implicit)]
1248 location: Location,
1249 },
1250
1251 #[snafu(display("Failed to read file metadata"))]
1252 Metadata {
1253 #[snafu(source)]
1254 error: std::io::Error,
1255 #[snafu(implicit)]
1256 location: Location,
1257 },
1258
1259 #[snafu(display("Failed to push value to bloom filter"))]
1260 PushBloomFilterValue {
1261 source: index::bloom_filter::error::Error,
1262 #[snafu(implicit)]
1263 location: Location,
1264 },
1265
1266 #[snafu(display("Failed to finish bloom filter"))]
1267 BloomFilterFinish {
1268 source: index::bloom_filter::error::Error,
1269 #[snafu(implicit)]
1270 location: Location,
1271 },
1272
1273 #[snafu(display("Manual compaction is override by following operations."))]
1274 ManualCompactionOverride {},
1275
1276 #[snafu(display("Manual compaction is already running for region {region_id}."))]
1277 ManualCompactionAlreadyRunning { region_id: RegionId },
1278
1279 #[snafu(display("Compaction is cancelled."))]
1280 CompactionCancelled {},
1281
1282 #[snafu(display("Flush is cancelled."))]
1283 FlushCancelled {},
1284
1285 #[snafu(display("Compaction memory exhausted for region {region_id} (policy: {policy})",))]
1286 CompactionMemoryExhausted {
1287 region_id: RegionId,
1288 policy: String,
1289 #[snafu(source)]
1290 source: common_memory_manager::Error,
1291 #[snafu(implicit)]
1292 location: Location,
1293 },
1294
1295 #[snafu(display(
1296 "Incompatible WAL provider change. This is typically caused by changing WAL provider in database config file without completely cleaning existing files. Global provider: {}, region provider: {}",
1297 global,
1298 region
1299 ))]
1300 IncompatibleWalProviderChange { global: String, region: String },
1301
1302 #[snafu(display("Expected mito manifest info"))]
1303 MitoManifestInfo {
1304 #[snafu(implicit)]
1305 location: Location,
1306 },
1307
1308 #[snafu(display("Failed to scan series"))]
1309 ScanSeries {
1310 #[snafu(implicit)]
1311 location: Location,
1312 source: Arc<Error>,
1313 },
1314
1315 #[snafu(display("Partition {} scan multiple times", partition))]
1316 ScanMultiTimes {
1317 partition: usize,
1318 #[snafu(implicit)]
1319 location: Location,
1320 },
1321
1322 #[snafu(display("Invalid partition expression: {}", expr))]
1323 InvalidPartitionExpr {
1324 expr: String,
1325 #[snafu(implicit)]
1326 location: Location,
1327 source: partition::error::Error,
1328 },
1329
1330 #[snafu(display("Failed to decode bulk wal entry"))]
1331 ConvertBulkWalEntry {
1332 #[snafu(implicit)]
1333 location: Location,
1334 source: common_grpc::Error,
1335 },
1336
1337 #[snafu(display("Failed to encode"))]
1338 Encode {
1339 #[snafu(implicit)]
1340 location: Location,
1341 source: mito_codec::error::Error,
1342 },
1343
1344 #[snafu(display("Failed to decode"))]
1345 Decode {
1346 #[snafu(implicit)]
1347 location: Location,
1348 source: mito_codec::error::Error,
1349 },
1350
1351 #[snafu(display("Unexpected: {reason}"))]
1352 Unexpected {
1353 reason: String,
1354 #[snafu(implicit)]
1355 location: Location,
1356 },
1357
1358 #[cfg(feature = "enterprise")]
1359 #[snafu(display("Failed to scan external range"))]
1360 ScanExternalRange {
1361 source: BoxedError,
1362 #[snafu(implicit)]
1363 location: Location,
1364 },
1365
1366 #[snafu(display(
1367 "Inconsistent timestamp column length, expect: {}, actual: {}",
1368 expected,
1369 actual
1370 ))]
1371 InconsistentTimestampLength {
1372 expected: usize,
1373 actual: usize,
1374 #[snafu(implicit)]
1375 location: Location,
1376 },
1377
1378 #[snafu(display(
1379 "Too many files to read concurrently: {}, max allowed: {}",
1380 actual,
1381 max
1382 ))]
1383 TooManyFilesToRead {
1384 actual: usize,
1385 max: usize,
1386 #[snafu(implicit)]
1387 location: Location,
1388 },
1389
1390 #[snafu(display("Duration out of range: {input:?}"))]
1391 DurationOutOfRange {
1392 input: std::time::Duration,
1393 #[snafu(source)]
1394 error: chrono::OutOfRangeError,
1395 #[snafu(implicit)]
1396 location: Location,
1397 },
1398
1399 #[snafu(display("GC job permit exhausted"))]
1400 TooManyGcJobs {
1401 #[snafu(implicit)]
1402 location: Location,
1403 },
1404
1405 #[snafu(display(
1406 "Staging partition expr mismatch, manifest: {:?}, request: {}",
1407 manifest_expr,
1408 request_expr
1409 ))]
1410 StagingPartitionExprMismatch {
1411 manifest_expr: Option<String>,
1412 request_expr: String,
1413 #[snafu(implicit)]
1414 location: Location,
1415 },
1416
1417 #[snafu(display(
1418 "Invalid source and target region, source: {}, target: {}",
1419 source_region_id,
1420 target_region_id
1421 ))]
1422 InvalidSourceAndTargetRegion {
1423 source_region_id: RegionId,
1424 target_region_id: RegionId,
1425 #[snafu(implicit)]
1426 location: Location,
1427 },
1428
1429 #[snafu(display("Failed to prune file"))]
1430 PruneFile {
1431 source: Arc<Error>,
1432 #[snafu(implicit)]
1433 location: Location,
1434 },
1435
1436 #[snafu(display("Failed to cast column"))]
1437 CastColumn {
1438 #[snafu(source)]
1439 error: datafusion::error::DataFusionError,
1440 #[snafu(implicit)]
1441 location: Location,
1442 },
1443
1444 #[snafu(display("Failed to generate Arrow schema from Parquet file: {}", file))]
1445 ParquetToArrowSchema {
1446 file: String,
1447 #[snafu(source)]
1448 error: parquet::errors::ParquetError,
1449 #[snafu(implicit)]
1450 location: Location,
1451 },
1452
1453 #[snafu(display(
1454 "Region {} is in {:?} state, expect: Writable, Staging or Downgrading",
1455 region_id,
1456 state
1457 ))]
1458 FlushableRegionState {
1459 region_id: RegionId,
1460 state: RegionRoleState,
1461 #[snafu(implicit)]
1462 location: Location,
1463 },
1464}
1465
1466pub type Result<T, E = Error> = std::result::Result<T, E>;
1467
1468impl Error {
1469 pub(crate) fn is_fill_default(&self) -> bool {
1471 matches!(self, Error::FillDefault { .. })
1472 }
1473
1474 pub(crate) fn is_object_not_found(&self) -> bool {
1476 match self {
1477 Error::OpenDal { error, .. } => error.kind() == ErrorKind::NotFound,
1478 Error::ManifestDeltaNotFound { .. } => true,
1479 Error::LoadSstMeta { source, .. }
1480 | Error::LoadParquetPage { source, .. }
1481 | Error::LoadRangeResult { source, .. } => source.is_object_not_found(),
1482 _ => false,
1483 }
1484 }
1485
1486 pub(crate) fn may_have_persisted_manifest_update(&self) -> bool {
1493 match self {
1494 Error::UpdateManifest { .. }
1495 | Error::RegionState { .. }
1496 | Error::RegionTruncated { .. }
1497 | Error::RegionStopped { .. }
1498 | Error::SerdeJson { .. }
1499 | Error::CompressObject { .. } => false,
1500 Error::OpenDal { error, .. } => !matches!(
1501 error.kind(),
1502 ErrorKind::Unsupported
1503 | ErrorKind::ConfigInvalid
1504 | ErrorKind::NotFound
1505 | ErrorKind::IsADirectory
1506 | ErrorKind::NotADirectory
1507 | ErrorKind::AlreadyExists
1508 | ErrorKind::IsSameFile
1509 | ErrorKind::ConditionNotMatch
1510 | ErrorKind::RangeNotSatisfied
1511 ),
1512 _ => true,
1513 }
1514 }
1515}
1516
1517impl ErrorExt for Error {
1518 fn status_code(&self) -> StatusCode {
1519 use Error::*;
1520
1521 match self {
1522 DataTypeMismatch { source, .. } => source.status_code(),
1523 OpenDal { .. } | ManifestDeltaNotFound { .. } | ReadParquet { .. } => {
1524 StatusCode::StorageUnavailable
1525 }
1526 WriteWal { source, .. }
1527 | ReadWal { source, .. }
1528 | DeleteWal { source, .. }
1529 | WaitWalDurable { source, .. }
1530 | CheckWalHistory { source, .. } => source.status_code(),
1531 CompressObject { .. }
1532 | DecompressObject { .. }
1533 | SerdeJson { .. }
1534 | Utf8 { .. }
1535 | NewRecordBatch { .. }
1536 | RegionCorrupted { .. }
1537 | InconsistentFile { .. }
1538 | CreateDefault { .. }
1539 | InvalidParquet { .. }
1540 | OperateAbortedIndex { .. }
1541 | IndexEncodeNull { .. }
1542 | NoCheckpoint { .. }
1543 | NoManifests { .. }
1544 | FilesLost { .. }
1545 | InstallManifestTo { .. }
1546 | Unexpected { .. }
1547 | SerializeColumnMetadata { .. }
1548 | SerializeManifest { .. }
1549 | StagingPartitionExprMismatch { .. } => StatusCode::Unexpected,
1550
1551 RegionNotFound { .. } => StatusCode::RegionNotFound,
1552 ObjectStoreNotFound { .. }
1553 | InvalidScanIndex { .. }
1554 | InvalidMeta { .. }
1555 | InvalidRequest { .. }
1556 | PartitionExprVersionMismatch { .. }
1557 | FillDefault { .. }
1558 | ConvertColumnDataType { .. }
1559 | ColumnNotFound { .. }
1560 | InvalidMetadata { .. }
1561 | InvalidRegionOptions { .. }
1562 | InvalidWalReadRequest { .. }
1563 | PartitionOutOfRange { .. }
1564 | ParseJobId { .. }
1565 | DurationOutOfRange { .. }
1566 | MissingOldManifest { .. }
1567 | MissingNewManifest { .. }
1568 | MissingManifest { .. }
1569 | NoOldManifests { .. }
1570 | MissingPartitionExpr { .. }
1571 | SerializePartitionExpr { .. }
1572 | InvalidSourceAndTargetRegion { .. } => StatusCode::InvalidArguments,
1573
1574 IncrementalQueryStale { .. } | SnapshotFenceStale { .. } => StatusCode::RequestOutdated,
1575
1576 SequenceRangeUnsupported { .. } => StatusCode::Unsupported,
1577
1578 RegionSequenceDomainBroken { .. }
1579 | RegionMetadataNotFound { .. }
1580 | Join { .. }
1581 | WorkerStopped { .. }
1582 | Recv { .. }
1583 | DecodeWal { .. }
1584 | ComputeArrow { .. }
1585 | EvalPartitionFilter { .. }
1586 | MergeCandidateSeries { .. }
1587 | BiErrors { .. }
1588 | StopScheduler { .. }
1589 | ComputeVector { .. }
1590 | EncodeMemtable { .. }
1591 | CreateDir { .. }
1592 | ReadDataPart { .. }
1593 | BuildEntry { .. }
1594 | Metadata { .. }
1595 | CastColumn { .. }
1596 | MitoManifestInfo { .. }
1597 | ParquetToArrowSchema { .. } => StatusCode::Internal,
1598
1599 FetchManifests { source, .. } => source.status_code(),
1600
1601 OpenRegion { source, .. } => source.status_code(),
1602
1603 WriteParquet { .. } => StatusCode::StorageUnavailable,
1604 WriteGroup { source, .. }
1605 | LoadSstMeta { source, .. }
1606 | LoadParquetPage { source, .. }
1607 | LoadRangeResult { source, .. } => source.status_code(),
1608 InvalidBatch { .. } => StatusCode::InvalidArguments,
1609 InvalidRecordBatch { .. } => StatusCode::InvalidArguments,
1610 ConvertVector { source, .. } => source.status_code(),
1611
1612 PrimaryKeyLengthMismatch { .. } => StatusCode::InvalidArguments,
1613 InvalidSender { .. } => StatusCode::InvalidArguments,
1614 InvalidSchedulerState { .. } => StatusCode::InvalidArguments,
1615 RegionRequirement { .. } => StatusCode::InvalidArguments,
1616 DeleteSsts { .. } | DeleteIndex { .. } | DeleteIndexes { .. } => {
1617 StatusCode::StorageUnavailable
1618 }
1619 FlushRegion { source, .. } | BuildIndexAsync { source, .. } => source.status_code(),
1620 IndexBuildIncomplete { .. } => StatusCode::IllegalState,
1621 RegionDropped { .. } => StatusCode::Cancelled,
1622 RegionClosed { .. } => StatusCode::Cancelled,
1623 StaleCompactionExecution { .. } => StatusCode::Cancelled,
1624 RegionTruncated { .. } => StatusCode::Cancelled,
1625 RejectWrite { .. } | RejectWriteInStaging { .. } => StatusCode::StorageUnavailable,
1626 CompactRegion { source, .. } => source.status_code(),
1627 EditRegion { source, .. } => source.status_code(),
1628 CompatReader { .. } => StatusCode::Unexpected,
1629 InvalidRegionRequest { source, .. } => source.status_code(),
1630 RegionState { .. } | UpdateManifest { .. } => StatusCode::RegionNotReady,
1631 RegionLeaseExpired { .. } | UnacknowledgedWrite { .. } => StatusCode::RegionNotReady,
1632 JsonOptions { .. } => StatusCode::InvalidArguments,
1633 EmptyRegionDir { .. } | EmptyManifestDir { .. } => StatusCode::RegionNotFound,
1634 ConvertValue { source, .. } => source.status_code(),
1635 ApplyBloomFilterIndex { source, .. } => source.status_code(),
1636 InvalidPartitionExpr { source, .. } => source.status_code(),
1637 BuildIndexApplier { source, .. }
1638 | PushIndexValue { source, .. }
1639 | ApplyInvertedIndex { source, .. }
1640 | IndexFinish { source, .. } => source.status_code(),
1641 PuffinReadBlob { source, .. }
1642 | PuffinAddBlob { source, .. }
1643 | PuffinInitStager { source, .. }
1644 | PuffinBuildReader { source, .. }
1645 | PuffinPurgeStager { source, .. } => source.status_code(),
1646 CleanDir { .. } => StatusCode::Unexpected,
1647 InvalidConfig { .. } => StatusCode::InvalidArguments,
1648 StaleLogEntry { .. }
1649 | InvalidNativeHistogramSubfield { .. }
1650 | InvalidNativeHistogramFieldId { .. } => StatusCode::Unexpected,
1651
1652 External { source, .. } => source.status_code(),
1653
1654 RecordBatch { source, .. } => source.status_code(),
1655
1656 Download { .. } | Upload { .. } => StatusCode::StorageUnavailable,
1657 ChecksumMismatch { .. } => StatusCode::Unexpected,
1658 RegionStopped { .. } => StatusCode::RegionNotReady,
1659 TimeRangePredicateOverflow { .. } => StatusCode::InvalidArguments,
1660 UnsupportedOperation { .. } => StatusCode::Unsupported,
1661 RemoteCompaction { .. } => StatusCode::Unexpected,
1662
1663 IndexOptions { source, .. } => source.status_code(),
1664 CompressionOptions { source, .. } => source.status_code(),
1665 CreateFulltextCreator { source, .. } => source.status_code(),
1666 CastVector { source, .. } => source.status_code(),
1667 FulltextPushText { source, .. }
1668 | FulltextFinish { source, .. }
1669 | ApplyFulltextIndex { source, .. } => source.status_code(),
1670 DecodeStats { .. }
1671 | StatsNotPresent { .. }
1672 | InvalidPrimaryKeyRange { .. }
1673 | DecodePrimaryKeyRange { .. } => StatusCode::Internal,
1674 RegionBusy { .. } => StatusCode::RegionBusy,
1675 GetSchemaMetadata { source, .. } => source.status_code(),
1676 Timeout { .. } => StatusCode::Cancelled,
1677
1678 DecodeArrowRowGroup { .. } => StatusCode::Internal,
1679
1680 PushBloomFilterValue { source, .. } | BloomFilterFinish { source, .. } => {
1681 source.status_code()
1682 }
1683
1684 ManualCompactionOverride {} | CompactionCancelled {} | FlushCancelled {} => {
1685 StatusCode::Cancelled
1686 }
1687
1688 ManualCompactionAlreadyRunning { .. } => StatusCode::RegionBusy,
1692
1693 CompactionMemoryExhausted { source, .. } => source.status_code(),
1694
1695 IncompatibleWalProviderChange { .. } => StatusCode::InvalidArguments,
1696
1697 ScanSeries { source, .. } => source.status_code(),
1698
1699 ScanMultiTimes { .. } => StatusCode::InvalidArguments,
1700 ConvertBulkWalEntry { source, .. } => source.status_code(),
1701
1702 Encode { source, .. } | Decode { source, .. } => source.status_code(),
1703
1704 #[cfg(feature = "enterprise")]
1705 ScanExternalRange { source, .. } => source.status_code(),
1706
1707 InconsistentTimestampLength { .. } => StatusCode::InvalidArguments,
1708
1709 TooManyFilesToRead { .. } | TooManyGcJobs { .. } => StatusCode::RateLimited,
1710
1711 PruneFile { source, .. } => source.status_code(),
1712
1713 FlushableRegionState { .. } => StatusCode::RegionNotReady,
1714 }
1715 }
1716
1717 fn as_any(&self) -> &dyn Any {
1718 self
1719 }
1720
1721 fn retry_hint(&self) -> RetryHint {
1722 use Error::*;
1723
1724 match self {
1725 PartitionExprVersionMismatch { .. }
1726 | RegionNotFound { .. }
1727 | RegionClosed { .. }
1728 | RejectWriteInStaging { .. }
1729 | RegionLeaseExpired { .. }
1730 | UnacknowledgedWrite { .. }
1731 | RegionState {
1732 state: RegionRoleState::Follower,
1733 ..
1734 } => RetryHint::RetryAfterRouteRefresh,
1735 ReadParquet { .. }
1736 | WriteParquet { .. }
1737 | RejectWrite { .. }
1738 | Download { .. }
1739 | Upload { .. }
1740 | RegionState { .. }
1741 | UpdateManifest { .. }
1742 | RegionStopped { .. }
1743 | RegionBusy { .. }
1744 | ManualCompactionAlreadyRunning { .. }
1745 | FlushableRegionState { .. }
1746 | ManifestDeltaNotFound { .. } => RetryHint::Retryable,
1747
1748 OpenDal { error, .. }
1749 | DeleteSsts { error, .. }
1750 | DeleteIndex { error, .. }
1751 | DeleteIndexes { error, .. } => retry_hint_from_opendal_error(error),
1752
1753 WriteWal { source, .. }
1754 | ReadWal { source, .. }
1755 | DeleteWal { source, .. }
1756 | WaitWalDurable { source, .. }
1757 | CheckWalHistory { source, .. }
1758 | FetchManifests { source, .. }
1759 | External { source, .. } => source.retry_hint(),
1760
1761 OpenRegion { source, .. }
1762 | LoadSstMeta { source, .. }
1763 | LoadParquetPage { source, .. }
1764 | LoadRangeResult { source, .. }
1765 | WriteGroup { source, .. }
1766 | FlushRegion { source, .. }
1767 | BuildIndexAsync { source, .. }
1768 | CompactRegion { source, .. }
1769 | EditRegion { source, .. }
1770 | ScanSeries { source, .. }
1771 | PruneFile { source, .. } => source.retry_hint(),
1772
1773 DataTypeMismatch { source, .. }
1774 | ConvertVector { source, .. }
1775 | ConvertValue { source, .. }
1776 | IndexOptions { source, .. }
1777 | CompressionOptions { source, .. }
1778 | CastVector { source, .. } => source.retry_hint(),
1779
1780 BuildIndexApplier { source, .. }
1781 | PushIndexValue { source, .. }
1782 | ApplyInvertedIndex { source, .. }
1783 | IndexFinish { source, .. } => source.retry_hint(),
1784
1785 ApplyBloomFilterIndex { source, .. }
1786 | PushBloomFilterValue { source, .. }
1787 | BloomFilterFinish { source, .. } => source.retry_hint(),
1788
1789 PuffinReadBlob { source, .. }
1790 | PuffinAddBlob { source, .. }
1791 | PuffinInitStager { source, .. }
1792 | PuffinBuildReader { source, .. }
1793 | PuffinPurgeStager { source, .. } => source.retry_hint(),
1794
1795 CreateFulltextCreator { source, .. }
1796 | FulltextPushText { source, .. }
1797 | FulltextFinish { source, .. }
1798 | ApplyFulltextIndex { source, .. } => source.retry_hint(),
1799
1800 InvalidRegionRequest { source, .. } => source.retry_hint(),
1801 InvalidPartitionExpr { source, .. } => source.retry_hint(),
1802 RecordBatch { source, .. } => source.retry_hint(),
1803 GetSchemaMetadata { source, .. } => source.retry_hint(),
1804 CompactionMemoryExhausted { source, .. } => source.retry_hint(),
1805 ConvertBulkWalEntry { source, .. } => source.retry_hint(),
1806 Encode { source, .. } | Decode { source, .. } => source.retry_hint(),
1807
1808 #[cfg(feature = "enterprise")]
1809 ScanExternalRange { source, .. } => source.retry_hint(),
1810
1811 _ => RetryHint::NonRetryable,
1812 }
1813 }
1814}
1815
1816#[cfg(test)]
1817mod tests {
1818 use snafu::IntoError;
1819
1820 use super::*;
1821 use crate::region::RegionLeaderState;
1822
1823 #[test]
1824 fn test_partition_version_mismatch_retry_hint() {
1825 let error = PartitionExprVersionMismatchSnafu {
1826 region_id: RegionId::new(1, 1),
1827 request_version: 1u64,
1828 expected_version: 2u64,
1829 }
1830 .build();
1831 assert_eq!(error.status_code(), StatusCode::InvalidArguments);
1832 assert_eq!(error.retry_hint(), RetryHint::RetryAfterRouteRefresh);
1833 }
1834
1835 #[test]
1836 fn test_region_state_retry_hint() {
1837 let region_id = RegionId::new(1, 1);
1838 let writable = RegionRoleState::Leader(RegionLeaderState::Writable);
1839 let follower_error = RegionStateSnafu {
1840 region_id,
1841 state: RegionRoleState::Follower,
1842 expect: writable,
1843 }
1844 .build();
1845 assert_eq!(
1846 follower_error.retry_hint(),
1847 RetryHint::RetryAfterRouteRefresh
1848 );
1849 assert_eq!(follower_error.status_code(), StatusCode::RegionNotReady);
1850 let leader_error = RegionStateSnafu {
1851 region_id,
1852 state: writable,
1853 expect: RegionRoleState::Follower,
1854 }
1855 .build();
1856 assert_eq!(leader_error.retry_hint(), RetryHint::Retryable);
1857 for (error, status, hint) in [
1858 (
1859 RejectWriteSnafu { region_id }.build(),
1860 StatusCode::StorageUnavailable,
1861 RetryHint::Retryable,
1862 ),
1863 (
1864 RejectWriteInStagingSnafu { region_id }.build(),
1865 StatusCode::StorageUnavailable,
1866 RetryHint::RetryAfterRouteRefresh,
1867 ),
1868 (
1869 RegionNotFoundSnafu { region_id }.build(),
1870 StatusCode::RegionNotFound,
1871 RetryHint::RetryAfterRouteRefresh,
1872 ),
1873 (
1874 RegionClosedSnafu { region_id }.build(),
1875 StatusCode::Cancelled,
1876 RetryHint::RetryAfterRouteRefresh,
1877 ),
1878 (
1879 RegionDroppedSnafu { region_id }.build(),
1880 StatusCode::Cancelled,
1881 RetryHint::NonRetryable,
1882 ),
1883 (
1884 RegionTruncatedSnafu { region_id }.build(),
1885 StatusCode::Cancelled,
1886 RetryHint::NonRetryable,
1887 ),
1888 ] {
1889 assert_eq!(error.status_code(), status);
1890 assert_eq!(error.retry_hint(), hint);
1891 }
1892 }
1893
1894 #[test]
1895 fn test_shared_sst_metadata_preserves_error_semantics() {
1896 for source in [
1897 OpenDalSnafu {}
1898 .into_error(object_store::Error::new(ErrorKind::NotFound, "missing SST")),
1899 OpenDalSnafu {}.into_error(object_store::Error::new(
1900 ErrorKind::Unexpected,
1901 "read failed",
1902 )),
1903 RejectWriteSnafu {
1904 region_id: RegionId::new(1, 1),
1905 }
1906 .build(),
1907 ] {
1908 let expected_not_found = source.is_object_not_found();
1909 let expected_status = source.status_code();
1910 let expected_retry = source.retry_hint();
1911 let source = Arc::new(source);
1912 for wrapped in [
1913 LoadSstMetaSnafu.into_error(source.clone()),
1914 LoadRangeResultSnafu.into_error(source),
1915 ] {
1916 assert_eq!(expected_not_found, wrapped.is_object_not_found());
1917 assert_eq!(expected_status, wrapped.status_code());
1918 assert_eq!(expected_retry, wrapped.retry_hint());
1919 }
1920 }
1921 }
1922
1923 #[test]
1924 fn test_manifest_update_persistence() {
1925 let rejected_kinds = [
1926 ErrorKind::Unsupported,
1927 ErrorKind::ConfigInvalid,
1928 ErrorKind::NotFound,
1929 ErrorKind::IsADirectory,
1930 ErrorKind::NotADirectory,
1931 ErrorKind::AlreadyExists,
1932 ErrorKind::IsSameFile,
1933 ErrorKind::ConditionNotMatch,
1934 ErrorKind::RangeNotSatisfied,
1935 ];
1936 for kind in rejected_kinds {
1937 let error = OpenDalSnafu {}.into_error(object_store::Error::new(kind, "test"));
1938 assert!(
1939 !error.may_have_persisted_manifest_update(),
1940 "error kind {kind:?} should prove the manifest was not persisted"
1941 );
1942 }
1943
1944 for kind in [
1946 ErrorKind::Unexpected,
1947 ErrorKind::RateLimited,
1948 ErrorKind::PermissionDenied,
1949 ] {
1950 let error = OpenDalSnafu {}.into_error(object_store::Error::new(kind, "test"));
1951 assert!(
1952 error.may_have_persisted_manifest_update(),
1953 "error kind {kind:?} should not prove the manifest was not persisted"
1954 );
1955 }
1956
1957 let region_id = RegionId::new(1, 1);
1958 let error = RegionTruncatedSnafu { region_id }.build();
1959 assert!(!error.may_have_persisted_manifest_update());
1960
1961 let error = RegionMetadataNotFoundSnafu {}.build();
1963 assert!(error.may_have_persisted_manifest_update());
1964 }
1965}