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 write parquet file"))]
202 WriteParquet {
203 #[snafu(source)]
204 error: parquet::errors::ParquetError,
205 #[snafu(implicit)]
206 location: Location,
207 },
208
209 #[snafu(display(
210 "Cannot assign a stable field id to native histogram sub-field '{}' of column id {} (unknown sub-field name or derived id overflows i32)",
211 field_name,
212 column_id
213 ))]
214 InvalidNativeHistogramSubfield {
215 column_id: i32,
216 field_name: String,
217 #[snafu(implicit)]
218 location: Location,
219 },
220
221 #[snafu(display(
222 "Native histogram column '{}' has no usable PARQUET:field_id to namespace its sub-field ids (missing, malformed, or exceeds i32::MAX)",
223 field_name
224 ))]
225 InvalidNativeHistogramFieldId {
226 field_name: String,
227 #[snafu(implicit)]
228 location: Location,
229 },
230
231 #[snafu(display("Region {} not found", region_id))]
232 RegionNotFound {
233 region_id: RegionId,
234 #[snafu(implicit)]
235 location: Location,
236 },
237
238 #[snafu(display("Object store not found: {}", object_store))]
239 ObjectStoreNotFound {
240 object_store: String,
241 #[snafu(implicit)]
242 location: Location,
243 },
244
245 #[snafu(display("Region {} is corrupted, reason: {}", region_id, reason))]
246 RegionCorrupted {
247 region_id: RegionId,
248 reason: String,
249 #[snafu(implicit)]
250 location: Location,
251 },
252
253 #[snafu(display("Invalid request to region {}, reason: {}", region_id, reason))]
254 InvalidRequest {
255 region_id: RegionId,
256 reason: String,
257 #[snafu(implicit)]
258 location: Location,
259 },
260
261 #[snafu(display(
262 "STALE_CURSOR: incremental query stale, region: {}, given_seq: {}, min_readable_seq: {}, retry_hint: FALLBACK_FULL_RECOMPUTE",
263 region_id,
264 given_seq,
265 min_readable_seq
266 ))]
267 IncrementalQueryStale {
268 region_id: RegionId,
269 given_seq: u64,
270 min_readable_seq: u64,
271 #[snafu(implicit)]
272 location: Location,
273 },
274
275 #[snafu(display(
276 "STALE_SNAPSHOT_FENCE: snapshot upper bound stale, region: {}, given_seq: {}, min_enforceable_seq: {}, retry_hint: REBIND_SNAPSHOT_FENCE",
277 region_id,
278 given_seq,
279 min_enforceable_seq
280 ))]
281 SnapshotFenceStale {
282 region_id: RegionId,
283 given_seq: u64,
284 min_enforceable_seq: u64,
285 #[snafu(implicit)]
286 location: Location,
287 },
288
289 #[snafu(display(
290 "SEQUENCE_RANGE_UNSUPPORTED: exact sequence-range read unsupported, region: {}, min_seq: {}, max_seq: {}, reason: {}, retry_hint: FALLBACK_MEMTABLE_ONLY_OR_FULL_RECOMPUTE",
291 region_id,
292 min_seq,
293 max_seq,
294 reason
295 ))]
296 SequenceRangeUnsupported {
297 region_id: RegionId,
298 min_seq: u64,
299 max_seq: u64,
300 reason: String,
301 #[snafu(implicit)]
302 location: Location,
303 },
304
305 #[snafu(display(
306 "region {} is unusable for sequence reads: file {} declares region {}",
307 region_id,
308 file_id,
309 file_region_id
310 ))]
311 RegionSequenceDomainBroken {
312 region_id: RegionId,
313 file_region_id: RegionId,
314 file_id: FileId,
315 #[snafu(implicit)]
316 location: Location,
317 },
318
319 #[snafu(display("Old manifest missing for region {}", region_id))]
320 MissingOldManifest {
321 region_id: RegionId,
322 #[snafu(implicit)]
323 location: Location,
324 },
325
326 #[snafu(display("New manifest missing for region {}", region_id))]
327 MissingNewManifest {
328 region_id: RegionId,
329 #[snafu(implicit)]
330 location: Location,
331 },
332
333 #[snafu(display("Manifest missing for region {}", region_id))]
334 MissingManifest {
335 region_id: RegionId,
336 #[snafu(implicit)]
337 location: Location,
338 },
339
340 #[snafu(display("File consistency check failed for file {}: {}", file_id, reason))]
341 InconsistentFile {
342 file_id: FileId,
343 reason: String,
344 #[snafu(implicit)]
345 location: Location,
346 },
347
348 #[snafu(display("Files lost during remapping: old={}, new={}", old_count, new_count))]
349 FilesLost {
350 old_count: usize,
351 new_count: usize,
352 #[snafu(implicit)]
353 location: Location,
354 },
355
356 #[snafu(display("No old manifests provided (need at least one for template)"))]
357 NoOldManifests {
358 #[snafu(implicit)]
359 location: Location,
360 },
361
362 #[snafu(display("Failed to fetch manifests"))]
363 FetchManifests {
364 #[snafu(implicit)]
365 location: Location,
366 source: BoxedError,
367 },
368
369 #[snafu(display("Partition expression missing for region {}", region_id))]
370 MissingPartitionExpr {
371 region_id: RegionId,
372 #[snafu(implicit)]
373 location: Location,
374 },
375
376 #[snafu(display("Failed to serialize partition expression: {}", source))]
377 SerializePartitionExpr {
378 #[snafu(source)]
379 source: PartitionError,
380 #[snafu(implicit)]
381 location: Location,
382 },
383
384 #[snafu(display(
385 "Failed to convert ConcreteDataType to ColumnDataType, reason: {}",
386 reason
387 ))]
388 ConvertColumnDataType {
389 reason: String,
390 source: api::error::Error,
391 #[snafu(implicit)]
392 location: Location,
393 },
394
395 #[snafu(display("Need to fill default value for region {}", region_id))]
398 FillDefault {
399 region_id: RegionId,
400 },
402
403 #[snafu(display(
404 "Failed to create default value for column {} of region {}",
405 column,
406 region_id
407 ))]
408 CreateDefault {
409 region_id: RegionId,
410 column: String,
411 source: datatypes::Error,
412 #[snafu(implicit)]
413 location: Location,
414 },
415
416 #[snafu(display("Failed to build entry, region_id: {}", region_id))]
417 BuildEntry {
418 region_id: RegionId,
419 #[snafu(implicit)]
420 location: Location,
421 source: BoxedError,
422 },
423
424 #[snafu(display("Failed to write WAL"))]
425 WriteWal {
426 #[snafu(implicit)]
427 location: Location,
428 source: BoxedError,
429 },
430
431 #[snafu(display("Failed to read WAL, provider: {}", provider))]
432 ReadWal {
433 provider: Provider,
434 #[snafu(implicit)]
435 location: Location,
436 source: BoxedError,
437 },
438
439 #[snafu(display("Failed to decode WAL entry, region_id: {}", region_id))]
440 DecodeWal {
441 region_id: RegionId,
442 #[snafu(implicit)]
443 location: Location,
444 #[snafu(source)]
445 error: DecodeError,
446 },
447
448 #[snafu(display("Failed to delete WAL, region_id: {}", region_id))]
449 DeleteWal {
450 region_id: RegionId,
451 #[snafu(implicit)]
452 location: Location,
453 source: BoxedError,
454 },
455
456 #[snafu(display("Failed to wait for the WAL to be durable, region_id: {}", region_id))]
457 WaitWalDurable {
458 region_id: RegionId,
459 #[snafu(implicit)]
460 location: Location,
461 source: BoxedError,
462 },
463
464 #[snafu(display("Failed to write region"))]
466 WriteGroup { source: Arc<Error> },
467
468 #[snafu(display("Invalid parquet SST file {}, reason: {}", file, reason))]
469 InvalidParquet {
470 file: String,
471 reason: String,
472 #[snafu(implicit)]
473 location: Location,
474 },
475
476 #[snafu(display("Invalid batch, {}", reason))]
477 InvalidBatch {
478 reason: String,
479 #[snafu(implicit)]
480 location: Location,
481 },
482
483 #[snafu(display("Invalid arrow record batch, {}", reason))]
484 InvalidRecordBatch {
485 reason: String,
486 #[snafu(implicit)]
487 location: Location,
488 },
489
490 #[snafu(display("Invalid wal read request, {}", reason))]
491 InvalidWalReadRequest {
492 reason: String,
493 #[snafu(implicit)]
494 location: Location,
495 },
496
497 #[snafu(display("Failed to convert array to vector"))]
498 ConvertVector {
499 #[snafu(implicit)]
500 location: Location,
501 source: datatypes::error::Error,
502 },
503
504 #[snafu(display("Failed to compute arrow arrays"))]
505 ComputeArrow {
506 #[snafu(implicit)]
507 location: Location,
508 #[snafu(source)]
509 error: datatypes::arrow::error::ArrowError,
510 },
511
512 #[snafu(display("Failed to evaluate partition filter"))]
513 EvalPartitionFilter {
514 #[snafu(implicit)]
515 location: Location,
516 #[snafu(source)]
517 error: datafusion::error::DataFusionError,
518 },
519
520 #[snafu(display("Failed to merge candidate series"))]
521 MergeCandidateSeries {
522 #[snafu(implicit)]
523 location: Location,
524 #[snafu(source)]
525 error: datafusion::error::DataFusionError,
526 },
527
528 #[snafu(display("Failed to compute vector"))]
529 ComputeVector {
530 #[snafu(implicit)]
531 location: Location,
532 source: datatypes::error::Error,
533 },
534
535 #[snafu(display("Primary key length mismatch, expect: {}, actual: {}", expect, actual))]
536 PrimaryKeyLengthMismatch {
537 expect: usize,
538 actual: usize,
539 #[snafu(implicit)]
540 location: Location,
541 },
542
543 #[snafu(display("Invalid sender",))]
544 InvalidSender {
545 #[snafu(implicit)]
546 location: Location,
547 },
548
549 #[snafu(display("Invalid scheduler state"))]
550 InvalidSchedulerState {
551 #[snafu(implicit)]
552 location: Location,
553 },
554
555 #[snafu(display("Failed to stop scheduler"))]
556 StopScheduler {
557 #[snafu(source)]
558 error: JoinError,
559 #[snafu(implicit)]
560 location: Location,
561 },
562
563 #[snafu(display(
564 "Failed to batch delete SST files, region id: {}, file ids: {:?}",
565 region_id,
566 file_ids
567 ))]
568 DeleteSsts {
569 region_id: RegionId,
570 file_ids: Vec<FileId>,
571 #[snafu(source)]
572 error: object_store::Error,
573 #[snafu(implicit)]
574 location: Location,
575 },
576
577 #[snafu(display("Failed to delete index file, file id: {}", file_id))]
578 DeleteIndex {
579 file_id: FileId,
580 #[snafu(source)]
581 error: object_store::Error,
582 #[snafu(implicit)]
583 location: Location,
584 },
585
586 #[snafu(display("Failed to batch delete index files, file ids: {:?}", file_ids))]
587 DeleteIndexes {
588 file_ids: Vec<FileId>,
589 #[snafu(source)]
590 error: object_store::Error,
591 #[snafu(implicit)]
592 location: Location,
593 },
594
595 #[snafu(display("Failed to flush region {}", region_id))]
596 FlushRegion {
597 region_id: RegionId,
598 source: Arc<Error>,
599 #[snafu(implicit)]
600 location: Location,
601 },
602
603 #[snafu(display("Region {} is dropped", region_id))]
604 RegionDropped {
605 region_id: RegionId,
606 #[snafu(implicit)]
607 location: Location,
608 },
609
610 #[snafu(display("Region {} is closed", region_id))]
611 RegionClosed {
612 region_id: RegionId,
613 #[snafu(implicit)]
614 location: Location,
615 },
616
617 #[snafu(display(
618 "Stale compaction execution for region {}, the region may have been reopened, truncated or the compaction was superseded",
619 region_id
620 ))]
621 StaleCompactionExecution {
622 region_id: RegionId,
623 #[snafu(implicit)]
624 location: Location,
625 },
626
627 #[snafu(display("Region {} is truncated", region_id))]
628 RegionTruncated {
629 region_id: RegionId,
630 #[snafu(implicit)]
631 location: Location,
632 },
633
634 #[snafu(display(
635 "Engine write buffer is full, rejecting write requests of region {}",
636 region_id,
637 ))]
638 RejectWrite {
639 region_id: RegionId,
640 #[snafu(implicit)]
641 location: Location,
642 },
643
644 #[snafu(display("Failed to compact region {}", region_id))]
645 CompactRegion {
646 region_id: RegionId,
647 source: Arc<Error>,
648 #[snafu(implicit)]
649 location: Location,
650 },
651
652 #[snafu(display("Failed to edit region {}", region_id))]
653 EditRegion {
654 region_id: RegionId,
655 source: Arc<Error>,
656 #[snafu(implicit)]
657 location: Location,
658 },
659
660 #[snafu(display(
661 "Failed to compat readers for region {}, reason: {}",
662 region_id,
663 reason,
664 ))]
665 CompatReader {
666 region_id: RegionId,
667 reason: String,
668 #[snafu(implicit)]
669 location: Location,
670 },
671
672 #[snafu(display("Invalue region req"))]
673 InvalidRegionRequest {
674 source: store_api::metadata::MetadataError,
675 #[snafu(implicit)]
676 location: Location,
677 },
678
679 #[snafu(display(
680 "Region {} is in {:?} state, which does not permit manifest updates.",
681 region_id,
682 state
683 ))]
684 UpdateManifest {
685 region_id: RegionId,
686 state: RegionRoleState,
687 #[snafu(implicit)]
688 location: Location,
689 },
690
691 #[snafu(display("Region {} is in {:?} state, expect: {:?}", region_id, state, expect))]
692 RegionState {
693 region_id: RegionId,
694 state: RegionRoleState,
695 expect: RegionRoleState,
696 #[snafu(implicit)]
697 location: Location,
698 },
699
700 #[snafu(display(
701 "Partition expr version mismatch for region {}: request {}, expected {}",
702 region_id,
703 request_version,
704 expected_version
705 ))]
706 PartitionExprVersionMismatch {
707 region_id: RegionId,
708 request_version: u64,
709 expected_version: u64,
710 #[snafu(implicit)]
711 location: Location,
712 },
713
714 #[snafu(display("Invalid options"))]
715 JsonOptions {
716 #[snafu(source)]
717 error: serde_json::Error,
718 #[snafu(implicit)]
719 location: Location,
720 },
721
722 #[snafu(display(
723 "Empty region directory, region_id: {}, region_dir: {}",
724 region_id,
725 region_dir,
726 ))]
727 EmptyRegionDir {
728 region_id: RegionId,
729 region_dir: String,
730 #[snafu(implicit)]
731 location: Location,
732 },
733
734 #[snafu(display("Empty manifest directory, manifest_dir: {}", manifest_dir,))]
735 EmptyManifestDir {
736 manifest_dir: String,
737 #[snafu(implicit)]
738 location: Location,
739 },
740
741 #[snafu(display("Column not found, column: {column}"))]
742 ColumnNotFound {
743 column: String,
744 #[snafu(implicit)]
745 location: Location,
746 },
747
748 #[snafu(display("Failed to build index applier"))]
749 BuildIndexApplier {
750 source: index::inverted_index::error::Error,
751 #[snafu(implicit)]
752 location: Location,
753 },
754
755 #[snafu(display("Failed to build index asynchronously in region {}", region_id))]
756 BuildIndexAsync {
757 region_id: RegionId,
758 source: Arc<Error>,
759 #[snafu(implicit)]
760 location: Location,
761 },
762
763 #[snafu(display("Failed to convert value"))]
764 ConvertValue {
765 source: datatypes::error::Error,
766 #[snafu(implicit)]
767 location: Location,
768 },
769
770 #[snafu(display("Failed to apply inverted index"))]
771 ApplyInvertedIndex {
772 source: index::inverted_index::error::Error,
773 #[snafu(implicit)]
774 location: Location,
775 },
776
777 #[snafu(display("Failed to apply bloom filter index"))]
778 ApplyBloomFilterIndex {
779 source: index::bloom_filter::error::Error,
780 #[snafu(implicit)]
781 location: Location,
782 },
783
784 #[snafu(display("Failed to push index value"))]
785 PushIndexValue {
786 source: index::inverted_index::error::Error,
787 #[snafu(implicit)]
788 location: Location,
789 },
790
791 #[snafu(display("Failed to write index completely"))]
792 IndexFinish {
793 source: index::inverted_index::error::Error,
794 #[snafu(implicit)]
795 location: Location,
796 },
797
798 #[snafu(display("Operate on aborted index"))]
799 OperateAbortedIndex {
800 #[snafu(implicit)]
801 location: Location,
802 },
803
804 #[snafu(display("Failed to read puffin blob"))]
805 PuffinReadBlob {
806 source: puffin::error::Error,
807 #[snafu(implicit)]
808 location: Location,
809 },
810
811 #[snafu(display("Failed to add blob to puffin file"))]
812 PuffinAddBlob {
813 source: puffin::error::Error,
814 #[snafu(implicit)]
815 location: Location,
816 },
817
818 #[snafu(display("Failed to clean dir {dir}"))]
819 CleanDir {
820 dir: String,
821 #[snafu(source)]
822 error: std::io::Error,
823 #[snafu(implicit)]
824 location: Location,
825 },
826
827 #[snafu(display("Invalid config, {reason}"))]
828 InvalidConfig {
829 reason: String,
830 #[snafu(implicit)]
831 location: Location,
832 },
833
834 #[snafu(display(
835 "Stale log entry found during replay, region: {}, flushed: {}, replayed: {}",
836 region_id,
837 flushed_entry_id,
838 unexpected_entry_id
839 ))]
840 StaleLogEntry {
841 region_id: RegionId,
842 flushed_entry_id: u64,
843 unexpected_entry_id: u64,
844 },
845
846 #[snafu(display(
847 "Failed to download file, region_id: {}, file_id: {}, file_type: {:?}",
848 region_id,
849 file_id,
850 file_type,
851 ))]
852 Download {
853 region_id: RegionId,
854 file_id: FileId,
855 file_type: FileType,
856 #[snafu(source)]
857 error: std::io::Error,
858 #[snafu(implicit)]
859 location: Location,
860 },
861
862 #[snafu(display(
863 "Failed to upload file, region_id: {}, file_id: {}, file_type: {:?}",
864 region_id,
865 file_id,
866 file_type,
867 ))]
868 Upload {
869 region_id: RegionId,
870 file_id: FileId,
871 file_type: FileType,
872 #[snafu(source)]
873 error: std::io::Error,
874 #[snafu(implicit)]
875 location: Location,
876 },
877
878 #[snafu(display("Failed to create directory {}", dir))]
879 CreateDir {
880 dir: String,
881 #[snafu(source)]
882 error: std::io::Error,
883 },
884
885 #[snafu(display("Record batch error"))]
886 RecordBatch {
887 source: common_recordbatch::error::Error,
888 #[snafu(implicit)]
889 location: Location,
890 },
891
892 #[snafu(display("BiErrors, first: {first}, second: {second}"))]
893 BiErrors {
894 first: Box<Error>,
895 second: Box<Error>,
896 #[snafu(implicit)]
897 location: Location,
898 },
899
900 #[snafu(display("Encode null value"))]
901 IndexEncodeNull {
902 #[snafu(implicit)]
903 location: Location,
904 },
905
906 #[snafu(display("Failed to encode memtable to Parquet bytes"))]
907 EncodeMemtable {
908 #[snafu(source)]
909 error: parquet::errors::ParquetError,
910 #[snafu(implicit)]
911 location: Location,
912 },
913
914 #[snafu(display("Partition {} out of range, {} in total", given, all))]
915 PartitionOutOfRange {
916 given: usize,
917 all: usize,
918 #[snafu(implicit)]
919 location: Location,
920 },
921
922 #[snafu(display("Failed to iter data part"))]
923 ReadDataPart {
924 #[snafu(implicit)]
925 location: Location,
926 #[snafu(source)]
927 error: parquet::errors::ParquetError,
928 },
929
930 #[snafu(display("Failed to read row group in memtable"))]
931 DecodeArrowRowGroup {
932 #[snafu(source)]
933 error: ArrowError,
934 #[snafu(implicit)]
935 location: Location,
936 },
937
938 #[snafu(display("Invalid region options, {}", reason))]
939 InvalidRegionOptions {
940 reason: String,
941 #[snafu(implicit)]
942 location: Location,
943 },
944
945 #[snafu(display("checksum mismatch (actual: {}, expected: {})", actual, expected))]
946 ChecksumMismatch { actual: u32, expected: u32 },
947
948 #[snafu(display(
949 "No checkpoint found, region: {}, last_version: {}",
950 region_id,
951 last_version
952 ))]
953 NoCheckpoint {
954 region_id: RegionId,
955 last_version: ManifestVersion,
956 #[snafu(implicit)]
957 location: Location,
958 },
959
960 #[snafu(display(
961 "No manifests found in range: [{}..{}), region: {}, last_version: {}",
962 start_version,
963 end_version,
964 region_id,
965 last_version
966 ))]
967 NoManifests {
968 region_id: RegionId,
969 start_version: ManifestVersion,
970 end_version: ManifestVersion,
971 last_version: ManifestVersion,
972 #[snafu(implicit)]
973 location: Location,
974 },
975
976 #[snafu(display(
977 "Failed to install manifest to {}, region: {}, available manifest version: {}, last version: {}",
978 target_version,
979 region_id,
980 available_version,
981 last_version
982 ))]
983 InstallManifestTo {
984 region_id: RegionId,
985 target_version: ManifestVersion,
986 available_version: ManifestVersion,
987 #[snafu(implicit)]
988 location: Location,
989 last_version: ManifestVersion,
990 },
991
992 #[snafu(display("Region {} is stopped", region_id))]
993 RegionStopped {
994 region_id: RegionId,
995 #[snafu(implicit)]
996 location: Location,
997 },
998
999 #[snafu(display(
1000 "Time range predicate overflows, timestamp: {:?}, target unit: {}",
1001 timestamp,
1002 unit
1003 ))]
1004 TimeRangePredicateOverflow {
1005 timestamp: Timestamp,
1006 unit: TimeUnit,
1007 #[snafu(implicit)]
1008 location: Location,
1009 },
1010
1011 #[snafu(display("Failed to open region"))]
1012 OpenRegion {
1013 #[snafu(implicit)]
1014 location: Location,
1015 source: Arc<Error>,
1016 },
1017
1018 #[snafu(display(
1019 "Region {} does not satisfy requirement '{}': {}",
1020 region_id,
1021 requirement,
1022 reason
1023 ))]
1024 RegionRequirement {
1025 region_id: RegionId,
1026 requirement: &'static str,
1027 reason: &'static str,
1028 #[snafu(implicit)]
1029 location: Location,
1030 },
1031
1032 #[snafu(display("Failed to parse job id"))]
1033 ParseJobId {
1034 #[snafu(implicit)]
1035 location: Location,
1036 #[snafu(source)]
1037 error: uuid::Error,
1038 },
1039
1040 #[snafu(display("Operation is not supported: {}", err_msg))]
1041 UnsupportedOperation {
1042 err_msg: String,
1043 #[snafu(implicit)]
1044 location: Location,
1045 },
1046
1047 #[snafu(display(
1048 "Failed to remotely compact region {} by job {:?} due to {}",
1049 region_id,
1050 job_id,
1051 reason
1052 ))]
1053 RemoteCompaction {
1054 region_id: RegionId,
1055 job_id: Option<JobId>,
1056 reason: String,
1057 #[snafu(implicit)]
1058 location: Location,
1059 },
1060
1061 #[snafu(display("Failed to initialize puffin stager"))]
1062 PuffinInitStager {
1063 source: puffin::error::Error,
1064 #[snafu(implicit)]
1065 location: Location,
1066 },
1067
1068 #[snafu(display("Failed to purge puffin stager"))]
1069 PuffinPurgeStager {
1070 source: puffin::error::Error,
1071 #[snafu(implicit)]
1072 location: Location,
1073 },
1074
1075 #[snafu(display("Failed to build puffin reader"))]
1076 PuffinBuildReader {
1077 source: puffin::error::Error,
1078 #[snafu(implicit)]
1079 location: Location,
1080 },
1081
1082 #[snafu(display("Failed to retrieve index options from column metadata"))]
1083 IndexOptions {
1084 #[snafu(implicit)]
1085 location: Location,
1086 source: datatypes::error::Error,
1087 column_name: String,
1088 },
1089
1090 #[snafu(display("Failed to create fulltext index creator"))]
1091 CreateFulltextCreator {
1092 source: index::fulltext_index::error::Error,
1093 #[snafu(implicit)]
1094 location: Location,
1095 },
1096
1097 #[snafu(display("Failed to cast vector of {from} to {to}"))]
1098 CastVector {
1099 #[snafu(implicit)]
1100 location: Location,
1101 from: ConcreteDataType,
1102 to: ConcreteDataType,
1103 source: datatypes::error::Error,
1104 },
1105
1106 #[snafu(display("Failed to push text to fulltext index"))]
1107 FulltextPushText {
1108 source: index::fulltext_index::error::Error,
1109 #[snafu(implicit)]
1110 location: Location,
1111 },
1112
1113 #[snafu(display("Failed to finalize fulltext index creator"))]
1114 FulltextFinish {
1115 source: index::fulltext_index::error::Error,
1116 #[snafu(implicit)]
1117 location: Location,
1118 },
1119
1120 #[snafu(display("Failed to apply fulltext index"))]
1121 ApplyFulltextIndex {
1122 source: index::fulltext_index::error::Error,
1123 #[snafu(implicit)]
1124 location: Location,
1125 },
1126
1127 #[snafu(display("SST file {} does not contain valid stats info", file_path))]
1128 StatsNotPresent {
1129 file_path: String,
1130 #[snafu(implicit)]
1131 location: Location,
1132 },
1133
1134 #[snafu(display("Failed to decode stats of file {}", file_path))]
1135 DecodeStats {
1136 file_path: String,
1137 #[snafu(implicit)]
1138 location: Location,
1139 },
1140
1141 #[snafu(display("Invalid SST primary key range: {reason}"))]
1142 InvalidPrimaryKeyRange {
1143 reason: String,
1144 #[snafu(implicit)]
1145 location: Location,
1146 },
1147
1148 #[snafu(display("Failed to decode SST primary key range {endpoint} endpoint"))]
1149 DecodePrimaryKeyRange {
1150 endpoint: &'static str,
1151 source: mito_codec::error::Error,
1152 #[snafu(implicit)]
1153 location: Location,
1154 },
1155
1156 #[snafu(display("Region {} is busy", region_id))]
1157 RegionBusy {
1158 region_id: RegionId,
1159 #[snafu(implicit)]
1160 location: Location,
1161 },
1162
1163 #[snafu(display("Failed to get schema metadata"))]
1164 GetSchemaMetadata {
1165 source: common_meta::error::Error,
1166 #[snafu(implicit)]
1167 location: Location,
1168 },
1169
1170 #[snafu(display("Timeout"))]
1171 Timeout {
1172 #[snafu(source)]
1173 error: Elapsed,
1174 #[snafu(implicit)]
1175 location: Location,
1176 },
1177
1178 #[snafu(display("Failed to read file metadata"))]
1179 Metadata {
1180 #[snafu(source)]
1181 error: std::io::Error,
1182 #[snafu(implicit)]
1183 location: Location,
1184 },
1185
1186 #[snafu(display("Failed to push value to bloom filter"))]
1187 PushBloomFilterValue {
1188 source: index::bloom_filter::error::Error,
1189 #[snafu(implicit)]
1190 location: Location,
1191 },
1192
1193 #[snafu(display("Failed to finish bloom filter"))]
1194 BloomFilterFinish {
1195 source: index::bloom_filter::error::Error,
1196 #[snafu(implicit)]
1197 location: Location,
1198 },
1199
1200 #[snafu(display("Manual compaction is override by following operations."))]
1201 ManualCompactionOverride {},
1202
1203 #[snafu(display("Manual compaction is already running for region {region_id}."))]
1204 ManualCompactionAlreadyRunning { region_id: RegionId },
1205
1206 #[snafu(display("Compaction is cancelled."))]
1207 CompactionCancelled {},
1208
1209 #[snafu(display("Flush is cancelled."))]
1210 FlushCancelled {},
1211
1212 #[snafu(display("Compaction memory exhausted for region {region_id} (policy: {policy})",))]
1213 CompactionMemoryExhausted {
1214 region_id: RegionId,
1215 policy: String,
1216 #[snafu(source)]
1217 source: common_memory_manager::Error,
1218 #[snafu(implicit)]
1219 location: Location,
1220 },
1221
1222 #[snafu(display(
1223 "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: {}",
1224 global,
1225 region
1226 ))]
1227 IncompatibleWalProviderChange { global: String, region: String },
1228
1229 #[snafu(display("Expected mito manifest info"))]
1230 MitoManifestInfo {
1231 #[snafu(implicit)]
1232 location: Location,
1233 },
1234
1235 #[snafu(display("Failed to scan series"))]
1236 ScanSeries {
1237 #[snafu(implicit)]
1238 location: Location,
1239 source: Arc<Error>,
1240 },
1241
1242 #[snafu(display("Partition {} scan multiple times", partition))]
1243 ScanMultiTimes {
1244 partition: usize,
1245 #[snafu(implicit)]
1246 location: Location,
1247 },
1248
1249 #[snafu(display("Invalid partition expression: {}", expr))]
1250 InvalidPartitionExpr {
1251 expr: String,
1252 #[snafu(implicit)]
1253 location: Location,
1254 source: partition::error::Error,
1255 },
1256
1257 #[snafu(display("Failed to decode bulk wal entry"))]
1258 ConvertBulkWalEntry {
1259 #[snafu(implicit)]
1260 location: Location,
1261 source: common_grpc::Error,
1262 },
1263
1264 #[snafu(display("Failed to encode"))]
1265 Encode {
1266 #[snafu(implicit)]
1267 location: Location,
1268 source: mito_codec::error::Error,
1269 },
1270
1271 #[snafu(display("Failed to decode"))]
1272 Decode {
1273 #[snafu(implicit)]
1274 location: Location,
1275 source: mito_codec::error::Error,
1276 },
1277
1278 #[snafu(display("Unexpected: {reason}"))]
1279 Unexpected {
1280 reason: String,
1281 #[snafu(implicit)]
1282 location: Location,
1283 },
1284
1285 #[cfg(feature = "enterprise")]
1286 #[snafu(display("Failed to scan external range"))]
1287 ScanExternalRange {
1288 source: BoxedError,
1289 #[snafu(implicit)]
1290 location: Location,
1291 },
1292
1293 #[snafu(display(
1294 "Inconsistent timestamp column length, expect: {}, actual: {}",
1295 expected,
1296 actual
1297 ))]
1298 InconsistentTimestampLength {
1299 expected: usize,
1300 actual: usize,
1301 #[snafu(implicit)]
1302 location: Location,
1303 },
1304
1305 #[snafu(display(
1306 "Too many files to read concurrently: {}, max allowed: {}",
1307 actual,
1308 max
1309 ))]
1310 TooManyFilesToRead {
1311 actual: usize,
1312 max: usize,
1313 #[snafu(implicit)]
1314 location: Location,
1315 },
1316
1317 #[snafu(display("Duration out of range: {input:?}"))]
1318 DurationOutOfRange {
1319 input: std::time::Duration,
1320 #[snafu(source)]
1321 error: chrono::OutOfRangeError,
1322 #[snafu(implicit)]
1323 location: Location,
1324 },
1325
1326 #[snafu(display("GC job permit exhausted"))]
1327 TooManyGcJobs {
1328 #[snafu(implicit)]
1329 location: Location,
1330 },
1331
1332 #[snafu(display(
1333 "Staging partition expr mismatch, manifest: {:?}, request: {}",
1334 manifest_expr,
1335 request_expr
1336 ))]
1337 StagingPartitionExprMismatch {
1338 manifest_expr: Option<String>,
1339 request_expr: String,
1340 #[snafu(implicit)]
1341 location: Location,
1342 },
1343
1344 #[snafu(display(
1345 "Invalid source and target region, source: {}, target: {}",
1346 source_region_id,
1347 target_region_id
1348 ))]
1349 InvalidSourceAndTargetRegion {
1350 source_region_id: RegionId,
1351 target_region_id: RegionId,
1352 #[snafu(implicit)]
1353 location: Location,
1354 },
1355
1356 #[snafu(display("Failed to prune file"))]
1357 PruneFile {
1358 source: Arc<Error>,
1359 #[snafu(implicit)]
1360 location: Location,
1361 },
1362
1363 #[snafu(display("Failed to cast column"))]
1364 CastColumn {
1365 #[snafu(source)]
1366 error: datafusion::error::DataFusionError,
1367 #[snafu(implicit)]
1368 location: Location,
1369 },
1370
1371 #[snafu(display("Failed to generate Arrow schema from Parquet file: {}", file))]
1372 ParquetToArrowSchema {
1373 file: String,
1374 #[snafu(source)]
1375 error: parquet::errors::ParquetError,
1376 #[snafu(implicit)]
1377 location: Location,
1378 },
1379
1380 #[snafu(display(
1381 "Region {} is in {:?} state, expect: Writable, Staging or Downgrading",
1382 region_id,
1383 state
1384 ))]
1385 FlushableRegionState {
1386 region_id: RegionId,
1387 state: RegionRoleState,
1388 #[snafu(implicit)]
1389 location: Location,
1390 },
1391}
1392
1393pub type Result<T, E = Error> = std::result::Result<T, E>;
1394
1395impl Error {
1396 pub(crate) fn is_fill_default(&self) -> bool {
1398 matches!(self, Error::FillDefault { .. })
1399 }
1400
1401 pub(crate) fn is_object_not_found(&self) -> bool {
1403 match self {
1404 Error::OpenDal { error, .. } => error.kind() == ErrorKind::NotFound,
1405 Error::ManifestDeltaNotFound { .. } => true,
1406 _ => false,
1407 }
1408 }
1409
1410 pub(crate) fn may_have_persisted_manifest_update(&self) -> bool {
1415 match self {
1416 Error::UpdateManifest { .. }
1417 | Error::RegionState { .. }
1418 | Error::RegionTruncated { .. }
1419 | Error::RegionStopped { .. }
1420 | Error::SerdeJson { .. }
1421 | Error::CompressObject { .. } => false,
1422 Error::OpenDal { error, .. } => !matches!(
1423 error.kind(),
1424 ErrorKind::Unsupported
1425 | ErrorKind::ConfigInvalid
1426 | ErrorKind::NotFound
1427 | ErrorKind::PermissionDenied
1428 | ErrorKind::IsADirectory
1429 | ErrorKind::NotADirectory
1430 | ErrorKind::AlreadyExists
1431 | ErrorKind::RateLimited
1432 | ErrorKind::IsSameFile
1433 | ErrorKind::ConditionNotMatch
1434 | ErrorKind::RangeNotSatisfied
1435 ),
1436 _ => true,
1437 }
1438 }
1439}
1440
1441impl ErrorExt for Error {
1442 fn status_code(&self) -> StatusCode {
1443 use Error::*;
1444
1445 match self {
1446 DataTypeMismatch { source, .. } => source.status_code(),
1447 OpenDal { .. } | ManifestDeltaNotFound { .. } | ReadParquet { .. } => {
1448 StatusCode::StorageUnavailable
1449 }
1450 WriteWal { source, .. }
1451 | ReadWal { source, .. }
1452 | DeleteWal { source, .. }
1453 | WaitWalDurable { source, .. } => source.status_code(),
1454 CompressObject { .. }
1455 | DecompressObject { .. }
1456 | SerdeJson { .. }
1457 | Utf8 { .. }
1458 | NewRecordBatch { .. }
1459 | RegionCorrupted { .. }
1460 | InconsistentFile { .. }
1461 | CreateDefault { .. }
1462 | InvalidParquet { .. }
1463 | OperateAbortedIndex { .. }
1464 | IndexEncodeNull { .. }
1465 | NoCheckpoint { .. }
1466 | NoManifests { .. }
1467 | FilesLost { .. }
1468 | InstallManifestTo { .. }
1469 | Unexpected { .. }
1470 | SerializeColumnMetadata { .. }
1471 | SerializeManifest { .. }
1472 | StagingPartitionExprMismatch { .. } => StatusCode::Unexpected,
1473
1474 RegionNotFound { .. } => StatusCode::RegionNotFound,
1475 ObjectStoreNotFound { .. }
1476 | InvalidScanIndex { .. }
1477 | InvalidMeta { .. }
1478 | InvalidRequest { .. }
1479 | PartitionExprVersionMismatch { .. }
1480 | FillDefault { .. }
1481 | ConvertColumnDataType { .. }
1482 | ColumnNotFound { .. }
1483 | InvalidMetadata { .. }
1484 | InvalidRegionOptions { .. }
1485 | InvalidWalReadRequest { .. }
1486 | PartitionOutOfRange { .. }
1487 | ParseJobId { .. }
1488 | DurationOutOfRange { .. }
1489 | MissingOldManifest { .. }
1490 | MissingNewManifest { .. }
1491 | MissingManifest { .. }
1492 | NoOldManifests { .. }
1493 | MissingPartitionExpr { .. }
1494 | SerializePartitionExpr { .. }
1495 | InvalidSourceAndTargetRegion { .. } => StatusCode::InvalidArguments,
1496
1497 IncrementalQueryStale { .. } | SnapshotFenceStale { .. } => StatusCode::RequestOutdated,
1498
1499 SequenceRangeUnsupported { .. } => StatusCode::Unsupported,
1500
1501 RegionSequenceDomainBroken { .. }
1502 | RegionMetadataNotFound { .. }
1503 | Join { .. }
1504 | WorkerStopped { .. }
1505 | Recv { .. }
1506 | DecodeWal { .. }
1507 | ComputeArrow { .. }
1508 | EvalPartitionFilter { .. }
1509 | MergeCandidateSeries { .. }
1510 | BiErrors { .. }
1511 | StopScheduler { .. }
1512 | ComputeVector { .. }
1513 | EncodeMemtable { .. }
1514 | CreateDir { .. }
1515 | ReadDataPart { .. }
1516 | BuildEntry { .. }
1517 | Metadata { .. }
1518 | CastColumn { .. }
1519 | MitoManifestInfo { .. }
1520 | ParquetToArrowSchema { .. } => StatusCode::Internal,
1521
1522 FetchManifests { source, .. } => source.status_code(),
1523
1524 OpenRegion { source, .. } => source.status_code(),
1525
1526 WriteParquet { .. } => StatusCode::StorageUnavailable,
1527 WriteGroup { source, .. } => source.status_code(),
1528 InvalidBatch { .. } => StatusCode::InvalidArguments,
1529 InvalidRecordBatch { .. } => StatusCode::InvalidArguments,
1530 ConvertVector { source, .. } => source.status_code(),
1531
1532 PrimaryKeyLengthMismatch { .. } => StatusCode::InvalidArguments,
1533 InvalidSender { .. } => StatusCode::InvalidArguments,
1534 InvalidSchedulerState { .. } => StatusCode::InvalidArguments,
1535 RegionRequirement { .. } => StatusCode::InvalidArguments,
1536 DeleteSsts { .. } | DeleteIndex { .. } | DeleteIndexes { .. } => {
1537 StatusCode::StorageUnavailable
1538 }
1539 FlushRegion { source, .. } | BuildIndexAsync { source, .. } => source.status_code(),
1540 RegionDropped { .. } => StatusCode::Cancelled,
1541 RegionClosed { .. } => StatusCode::Cancelled,
1542 StaleCompactionExecution { .. } => StatusCode::Cancelled,
1543 RegionTruncated { .. } => StatusCode::Cancelled,
1544 RejectWrite { .. } => StatusCode::StorageUnavailable,
1545 CompactRegion { source, .. } => source.status_code(),
1546 EditRegion { source, .. } => source.status_code(),
1547 CompatReader { .. } => StatusCode::Unexpected,
1548 InvalidRegionRequest { source, .. } => source.status_code(),
1549 RegionState { .. } | UpdateManifest { .. } => StatusCode::RegionNotReady,
1550 JsonOptions { .. } => StatusCode::InvalidArguments,
1551 EmptyRegionDir { .. } | EmptyManifestDir { .. } => StatusCode::RegionNotFound,
1552 ConvertValue { source, .. } => source.status_code(),
1553 ApplyBloomFilterIndex { source, .. } => source.status_code(),
1554 InvalidPartitionExpr { source, .. } => source.status_code(),
1555 BuildIndexApplier { source, .. }
1556 | PushIndexValue { source, .. }
1557 | ApplyInvertedIndex { source, .. }
1558 | IndexFinish { source, .. } => source.status_code(),
1559 PuffinReadBlob { source, .. }
1560 | PuffinAddBlob { source, .. }
1561 | PuffinInitStager { source, .. }
1562 | PuffinBuildReader { source, .. }
1563 | PuffinPurgeStager { source, .. } => source.status_code(),
1564 CleanDir { .. } => StatusCode::Unexpected,
1565 InvalidConfig { .. } => StatusCode::InvalidArguments,
1566 StaleLogEntry { .. }
1567 | InvalidNativeHistogramSubfield { .. }
1568 | InvalidNativeHistogramFieldId { .. } => StatusCode::Unexpected,
1569
1570 External { source, .. } => source.status_code(),
1571
1572 RecordBatch { source, .. } => source.status_code(),
1573
1574 Download { .. } | Upload { .. } => StatusCode::StorageUnavailable,
1575 ChecksumMismatch { .. } => StatusCode::Unexpected,
1576 RegionStopped { .. } => StatusCode::RegionNotReady,
1577 TimeRangePredicateOverflow { .. } => StatusCode::InvalidArguments,
1578 UnsupportedOperation { .. } => StatusCode::Unsupported,
1579 RemoteCompaction { .. } => StatusCode::Unexpected,
1580
1581 IndexOptions { source, .. } => source.status_code(),
1582 CreateFulltextCreator { source, .. } => source.status_code(),
1583 CastVector { source, .. } => source.status_code(),
1584 FulltextPushText { source, .. }
1585 | FulltextFinish { source, .. }
1586 | ApplyFulltextIndex { source, .. } => source.status_code(),
1587 DecodeStats { .. }
1588 | StatsNotPresent { .. }
1589 | InvalidPrimaryKeyRange { .. }
1590 | DecodePrimaryKeyRange { .. } => StatusCode::Internal,
1591 RegionBusy { .. } => StatusCode::RegionBusy,
1592 GetSchemaMetadata { source, .. } => source.status_code(),
1593 Timeout { .. } => StatusCode::Cancelled,
1594
1595 DecodeArrowRowGroup { .. } => StatusCode::Internal,
1596
1597 PushBloomFilterValue { source, .. } | BloomFilterFinish { source, .. } => {
1598 source.status_code()
1599 }
1600
1601 ManualCompactionOverride {} | CompactionCancelled {} | FlushCancelled {} => {
1602 StatusCode::Cancelled
1603 }
1604
1605 ManualCompactionAlreadyRunning { .. } => StatusCode::RegionBusy,
1609
1610 CompactionMemoryExhausted { source, .. } => source.status_code(),
1611
1612 IncompatibleWalProviderChange { .. } => StatusCode::InvalidArguments,
1613
1614 ScanSeries { source, .. } => source.status_code(),
1615
1616 ScanMultiTimes { .. } => StatusCode::InvalidArguments,
1617 ConvertBulkWalEntry { source, .. } => source.status_code(),
1618
1619 Encode { source, .. } | Decode { source, .. } => source.status_code(),
1620
1621 #[cfg(feature = "enterprise")]
1622 ScanExternalRange { source, .. } => source.status_code(),
1623
1624 InconsistentTimestampLength { .. } => StatusCode::InvalidArguments,
1625
1626 TooManyFilesToRead { .. } | TooManyGcJobs { .. } => StatusCode::RateLimited,
1627
1628 PruneFile { source, .. } => source.status_code(),
1629
1630 FlushableRegionState { .. } => StatusCode::RegionNotReady,
1631 }
1632 }
1633
1634 fn as_any(&self) -> &dyn Any {
1635 self
1636 }
1637
1638 fn retry_hint(&self) -> RetryHint {
1639 use Error::*;
1640
1641 match self {
1642 ReadParquet { .. }
1643 | WriteParquet { .. }
1644 | RejectWrite { .. }
1645 | Download { .. }
1646 | Upload { .. }
1647 | RegionState { .. }
1648 | UpdateManifest { .. }
1649 | RegionStopped { .. }
1650 | RegionBusy { .. }
1651 | ManualCompactionAlreadyRunning { .. }
1652 | FlushableRegionState { .. }
1653 | ManifestDeltaNotFound { .. } => RetryHint::Retryable,
1654
1655 OpenDal { error, .. }
1656 | DeleteSsts { error, .. }
1657 | DeleteIndex { error, .. }
1658 | DeleteIndexes { error, .. } => retry_hint_from_opendal_error(error),
1659
1660 WriteWal { source, .. }
1661 | ReadWal { source, .. }
1662 | DeleteWal { source, .. }
1663 | WaitWalDurable { source, .. }
1664 | FetchManifests { source, .. }
1665 | External { source, .. } => source.retry_hint(),
1666
1667 OpenRegion { source, .. }
1668 | WriteGroup { source, .. }
1669 | FlushRegion { source, .. }
1670 | BuildIndexAsync { source, .. }
1671 | CompactRegion { source, .. }
1672 | EditRegion { source, .. }
1673 | ScanSeries { source, .. }
1674 | PruneFile { source, .. } => source.retry_hint(),
1675
1676 DataTypeMismatch { source, .. }
1677 | ConvertVector { source, .. }
1678 | ConvertValue { source, .. }
1679 | IndexOptions { source, .. }
1680 | CastVector { source, .. } => source.retry_hint(),
1681
1682 BuildIndexApplier { source, .. }
1683 | PushIndexValue { source, .. }
1684 | ApplyInvertedIndex { source, .. }
1685 | IndexFinish { source, .. } => source.retry_hint(),
1686
1687 ApplyBloomFilterIndex { source, .. }
1688 | PushBloomFilterValue { source, .. }
1689 | BloomFilterFinish { source, .. } => source.retry_hint(),
1690
1691 PuffinReadBlob { source, .. }
1692 | PuffinAddBlob { source, .. }
1693 | PuffinInitStager { source, .. }
1694 | PuffinBuildReader { source, .. }
1695 | PuffinPurgeStager { source, .. } => source.retry_hint(),
1696
1697 CreateFulltextCreator { source, .. }
1698 | FulltextPushText { source, .. }
1699 | FulltextFinish { source, .. }
1700 | ApplyFulltextIndex { source, .. } => source.retry_hint(),
1701
1702 InvalidRegionRequest { source, .. } => source.retry_hint(),
1703 InvalidPartitionExpr { source, .. } => source.retry_hint(),
1704 RecordBatch { source, .. } => source.retry_hint(),
1705 GetSchemaMetadata { source, .. } => source.retry_hint(),
1706 CompactionMemoryExhausted { source, .. } => source.retry_hint(),
1707 ConvertBulkWalEntry { source, .. } => source.retry_hint(),
1708 Encode { source, .. } | Decode { source, .. } => source.retry_hint(),
1709
1710 #[cfg(feature = "enterprise")]
1711 ScanExternalRange { source, .. } => source.retry_hint(),
1712
1713 _ => RetryHint::NonRetryable,
1714 }
1715 }
1716}
1717
1718#[cfg(test)]
1719mod tests {
1720 use snafu::IntoError;
1721
1722 use super::*;
1723
1724 #[test]
1725 fn test_manifest_update_persistence() {
1726 let rejected_kinds = [
1727 ErrorKind::Unsupported,
1728 ErrorKind::ConfigInvalid,
1729 ErrorKind::NotFound,
1730 ErrorKind::PermissionDenied,
1731 ErrorKind::IsADirectory,
1732 ErrorKind::NotADirectory,
1733 ErrorKind::AlreadyExists,
1734 ErrorKind::RateLimited,
1735 ErrorKind::IsSameFile,
1736 ErrorKind::ConditionNotMatch,
1737 ErrorKind::RangeNotSatisfied,
1738 ];
1739 for kind in rejected_kinds {
1740 let error = OpenDalSnafu {}.into_error(object_store::Error::new(kind, "test"));
1741 assert!(
1742 !error.may_have_persisted_manifest_update(),
1743 "error kind {kind:?} should prove the manifest was not persisted"
1744 );
1745 }
1746
1747 let error =
1748 OpenDalSnafu {}.into_error(object_store::Error::new(ErrorKind::Unexpected, "test"));
1749 assert!(error.may_have_persisted_manifest_update());
1750
1751 let region_id = RegionId::new(1, 1);
1752 let error = RegionTruncatedSnafu { region_id }.build();
1753 assert!(!error.may_have_persisted_manifest_update());
1754
1755 let error = RegionMetadataNotFoundSnafu {}.build();
1757 assert!(error.may_have_persisted_manifest_update());
1758 }
1759}