Skip to main content

mito2/
error.rs

1// Copyright 2023 Greptime Team
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use 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    /// An error type to indicate that schema is changed and we need
396    /// to fill default values again.
397    #[snafu(display("Need to fill default value for region {}", region_id))]
398    FillDefault {
399        region_id: RegionId,
400        // The error is for internal use so we don't need a location.
401    },
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    // Shared error for each writer in the write group.
457    #[snafu(display("Failed to write region"))]
458    WriteGroup { source: Arc<Error> },
459
460    #[snafu(display("Invalid parquet SST file {}, reason: {}", file, reason))]
461    InvalidParquet {
462        file: String,
463        reason: String,
464        #[snafu(implicit)]
465        location: Location,
466    },
467
468    #[snafu(display("Invalid batch, {}", reason))]
469    InvalidBatch {
470        reason: String,
471        #[snafu(implicit)]
472        location: Location,
473    },
474
475    #[snafu(display("Invalid arrow record batch, {}", reason))]
476    InvalidRecordBatch {
477        reason: String,
478        #[snafu(implicit)]
479        location: Location,
480    },
481
482    #[snafu(display("Invalid wal read request, {}", reason))]
483    InvalidWalReadRequest {
484        reason: String,
485        #[snafu(implicit)]
486        location: Location,
487    },
488
489    #[snafu(display("Failed to convert array to vector"))]
490    ConvertVector {
491        #[snafu(implicit)]
492        location: Location,
493        source: datatypes::error::Error,
494    },
495
496    #[snafu(display("Failed to compute arrow arrays"))]
497    ComputeArrow {
498        #[snafu(implicit)]
499        location: Location,
500        #[snafu(source)]
501        error: datatypes::arrow::error::ArrowError,
502    },
503
504    #[snafu(display("Failed to evaluate partition filter"))]
505    EvalPartitionFilter {
506        #[snafu(implicit)]
507        location: Location,
508        #[snafu(source)]
509        error: datafusion::error::DataFusionError,
510    },
511
512    #[snafu(display("Failed to merge candidate series"))]
513    MergeCandidateSeries {
514        #[snafu(implicit)]
515        location: Location,
516        #[snafu(source)]
517        error: datafusion::error::DataFusionError,
518    },
519
520    #[snafu(display("Failed to compute vector"))]
521    ComputeVector {
522        #[snafu(implicit)]
523        location: Location,
524        source: datatypes::error::Error,
525    },
526
527    #[snafu(display("Primary key length mismatch, expect: {}, actual: {}", expect, actual))]
528    PrimaryKeyLengthMismatch {
529        expect: usize,
530        actual: usize,
531        #[snafu(implicit)]
532        location: Location,
533    },
534
535    #[snafu(display("Invalid sender",))]
536    InvalidSender {
537        #[snafu(implicit)]
538        location: Location,
539    },
540
541    #[snafu(display("Invalid scheduler state"))]
542    InvalidSchedulerState {
543        #[snafu(implicit)]
544        location: Location,
545    },
546
547    #[snafu(display("Failed to stop scheduler"))]
548    StopScheduler {
549        #[snafu(source)]
550        error: JoinError,
551        #[snafu(implicit)]
552        location: Location,
553    },
554
555    #[snafu(display(
556        "Failed to batch delete SST files, region id: {}, file ids: {:?}",
557        region_id,
558        file_ids
559    ))]
560    DeleteSsts {
561        region_id: RegionId,
562        file_ids: Vec<FileId>,
563        #[snafu(source)]
564        error: object_store::Error,
565        #[snafu(implicit)]
566        location: Location,
567    },
568
569    #[snafu(display("Failed to delete index file, file id: {}", file_id))]
570    DeleteIndex {
571        file_id: FileId,
572        #[snafu(source)]
573        error: object_store::Error,
574        #[snafu(implicit)]
575        location: Location,
576    },
577
578    #[snafu(display("Failed to batch delete index files, file ids: {:?}", file_ids))]
579    DeleteIndexes {
580        file_ids: Vec<FileId>,
581        #[snafu(source)]
582        error: object_store::Error,
583        #[snafu(implicit)]
584        location: Location,
585    },
586
587    #[snafu(display("Failed to flush region {}", region_id))]
588    FlushRegion {
589        region_id: RegionId,
590        source: Arc<Error>,
591        #[snafu(implicit)]
592        location: Location,
593    },
594
595    #[snafu(display("Region {} is dropped", region_id))]
596    RegionDropped {
597        region_id: RegionId,
598        #[snafu(implicit)]
599        location: Location,
600    },
601
602    #[snafu(display("Region {} is closed", region_id))]
603    RegionClosed {
604        region_id: RegionId,
605        #[snafu(implicit)]
606        location: Location,
607    },
608
609    #[snafu(display(
610        "Stale compaction execution for region {}, the region may have been reopened, truncated or the compaction was superseded",
611        region_id
612    ))]
613    StaleCompactionExecution {
614        region_id: RegionId,
615        #[snafu(implicit)]
616        location: Location,
617    },
618
619    #[snafu(display("Region {} is truncated", region_id))]
620    RegionTruncated {
621        region_id: RegionId,
622        #[snafu(implicit)]
623        location: Location,
624    },
625
626    #[snafu(display(
627        "Engine write buffer is full, rejecting write requests of region {}",
628        region_id,
629    ))]
630    RejectWrite {
631        region_id: RegionId,
632        #[snafu(implicit)]
633        location: Location,
634    },
635
636    #[snafu(display("Failed to compact region {}", region_id))]
637    CompactRegion {
638        region_id: RegionId,
639        source: Arc<Error>,
640        #[snafu(implicit)]
641        location: Location,
642    },
643
644    #[snafu(display("Failed to edit region {}", region_id))]
645    EditRegion {
646        region_id: RegionId,
647        source: Arc<Error>,
648        #[snafu(implicit)]
649        location: Location,
650    },
651
652    #[snafu(display(
653        "Failed to compat readers for region {}, reason: {}",
654        region_id,
655        reason,
656    ))]
657    CompatReader {
658        region_id: RegionId,
659        reason: String,
660        #[snafu(implicit)]
661        location: Location,
662    },
663
664    #[snafu(display("Invalue region req"))]
665    InvalidRegionRequest {
666        source: store_api::metadata::MetadataError,
667        #[snafu(implicit)]
668        location: Location,
669    },
670
671    #[snafu(display(
672        "Region {} is in {:?} state, which does not permit manifest updates.",
673        region_id,
674        state
675    ))]
676    UpdateManifest {
677        region_id: RegionId,
678        state: RegionRoleState,
679        #[snafu(implicit)]
680        location: Location,
681    },
682
683    #[snafu(display("Region {} is in {:?} state, expect: {:?}", region_id, state, expect))]
684    RegionState {
685        region_id: RegionId,
686        state: RegionRoleState,
687        expect: RegionRoleState,
688        #[snafu(implicit)]
689        location: Location,
690    },
691
692    #[snafu(display(
693        "Partition expr version mismatch for region {}: request {}, expected {}",
694        region_id,
695        request_version,
696        expected_version
697    ))]
698    PartitionExprVersionMismatch {
699        region_id: RegionId,
700        request_version: u64,
701        expected_version: u64,
702        #[snafu(implicit)]
703        location: Location,
704    },
705
706    #[snafu(display("Invalid options"))]
707    JsonOptions {
708        #[snafu(source)]
709        error: serde_json::Error,
710        #[snafu(implicit)]
711        location: Location,
712    },
713
714    #[snafu(display(
715        "Empty region directory, region_id: {}, region_dir: {}",
716        region_id,
717        region_dir,
718    ))]
719    EmptyRegionDir {
720        region_id: RegionId,
721        region_dir: String,
722        #[snafu(implicit)]
723        location: Location,
724    },
725
726    #[snafu(display("Empty manifest directory, manifest_dir: {}", manifest_dir,))]
727    EmptyManifestDir {
728        manifest_dir: String,
729        #[snafu(implicit)]
730        location: Location,
731    },
732
733    #[snafu(display("Column not found, column: {column}"))]
734    ColumnNotFound {
735        column: String,
736        #[snafu(implicit)]
737        location: Location,
738    },
739
740    #[snafu(display("Failed to build index applier"))]
741    BuildIndexApplier {
742        source: index::inverted_index::error::Error,
743        #[snafu(implicit)]
744        location: Location,
745    },
746
747    #[snafu(display("Failed to build index asynchronously in region {}", region_id))]
748    BuildIndexAsync {
749        region_id: RegionId,
750        source: Arc<Error>,
751        #[snafu(implicit)]
752        location: Location,
753    },
754
755    #[snafu(display("Failed to convert value"))]
756    ConvertValue {
757        source: datatypes::error::Error,
758        #[snafu(implicit)]
759        location: Location,
760    },
761
762    #[snafu(display("Failed to apply inverted index"))]
763    ApplyInvertedIndex {
764        source: index::inverted_index::error::Error,
765        #[snafu(implicit)]
766        location: Location,
767    },
768
769    #[snafu(display("Failed to apply bloom filter index"))]
770    ApplyBloomFilterIndex {
771        source: index::bloom_filter::error::Error,
772        #[snafu(implicit)]
773        location: Location,
774    },
775
776    #[snafu(display("Failed to push index value"))]
777    PushIndexValue {
778        source: index::inverted_index::error::Error,
779        #[snafu(implicit)]
780        location: Location,
781    },
782
783    #[snafu(display("Failed to write index completely"))]
784    IndexFinish {
785        source: index::inverted_index::error::Error,
786        #[snafu(implicit)]
787        location: Location,
788    },
789
790    #[snafu(display("Operate on aborted index"))]
791    OperateAbortedIndex {
792        #[snafu(implicit)]
793        location: Location,
794    },
795
796    #[snafu(display("Failed to read puffin blob"))]
797    PuffinReadBlob {
798        source: puffin::error::Error,
799        #[snafu(implicit)]
800        location: Location,
801    },
802
803    #[snafu(display("Failed to add blob to puffin file"))]
804    PuffinAddBlob {
805        source: puffin::error::Error,
806        #[snafu(implicit)]
807        location: Location,
808    },
809
810    #[snafu(display("Failed to clean dir {dir}"))]
811    CleanDir {
812        dir: String,
813        #[snafu(source)]
814        error: std::io::Error,
815        #[snafu(implicit)]
816        location: Location,
817    },
818
819    #[snafu(display("Invalid config, {reason}"))]
820    InvalidConfig {
821        reason: String,
822        #[snafu(implicit)]
823        location: Location,
824    },
825
826    #[snafu(display(
827        "Stale log entry found during replay, region: {}, flushed: {}, replayed: {}",
828        region_id,
829        flushed_entry_id,
830        unexpected_entry_id
831    ))]
832    StaleLogEntry {
833        region_id: RegionId,
834        flushed_entry_id: u64,
835        unexpected_entry_id: u64,
836    },
837
838    #[snafu(display(
839        "Failed to download file, region_id: {}, file_id: {}, file_type: {:?}",
840        region_id,
841        file_id,
842        file_type,
843    ))]
844    Download {
845        region_id: RegionId,
846        file_id: FileId,
847        file_type: FileType,
848        #[snafu(source)]
849        error: std::io::Error,
850        #[snafu(implicit)]
851        location: Location,
852    },
853
854    #[snafu(display(
855        "Failed to upload file, region_id: {}, file_id: {}, file_type: {:?}",
856        region_id,
857        file_id,
858        file_type,
859    ))]
860    Upload {
861        region_id: RegionId,
862        file_id: FileId,
863        file_type: FileType,
864        #[snafu(source)]
865        error: std::io::Error,
866        #[snafu(implicit)]
867        location: Location,
868    },
869
870    #[snafu(display("Failed to create directory {}", dir))]
871    CreateDir {
872        dir: String,
873        #[snafu(source)]
874        error: std::io::Error,
875    },
876
877    #[snafu(display("Record batch error"))]
878    RecordBatch {
879        source: common_recordbatch::error::Error,
880        #[snafu(implicit)]
881        location: Location,
882    },
883
884    #[snafu(display("BiErrors, first: {first}, second: {second}"))]
885    BiErrors {
886        first: Box<Error>,
887        second: Box<Error>,
888        #[snafu(implicit)]
889        location: Location,
890    },
891
892    #[snafu(display("Encode null value"))]
893    IndexEncodeNull {
894        #[snafu(implicit)]
895        location: Location,
896    },
897
898    #[snafu(display("Failed to encode memtable to Parquet bytes"))]
899    EncodeMemtable {
900        #[snafu(source)]
901        error: parquet::errors::ParquetError,
902        #[snafu(implicit)]
903        location: Location,
904    },
905
906    #[snafu(display("Partition {} out of range, {} in total", given, all))]
907    PartitionOutOfRange {
908        given: usize,
909        all: usize,
910        #[snafu(implicit)]
911        location: Location,
912    },
913
914    #[snafu(display("Failed to iter data part"))]
915    ReadDataPart {
916        #[snafu(implicit)]
917        location: Location,
918        #[snafu(source)]
919        error: parquet::errors::ParquetError,
920    },
921
922    #[snafu(display("Failed to read row group in memtable"))]
923    DecodeArrowRowGroup {
924        #[snafu(source)]
925        error: ArrowError,
926        #[snafu(implicit)]
927        location: Location,
928    },
929
930    #[snafu(display("Invalid region options, {}", reason))]
931    InvalidRegionOptions {
932        reason: String,
933        #[snafu(implicit)]
934        location: Location,
935    },
936
937    #[snafu(display("checksum mismatch (actual: {}, expected: {})", actual, expected))]
938    ChecksumMismatch { actual: u32, expected: u32 },
939
940    #[snafu(display(
941        "No checkpoint found, region: {}, last_version: {}",
942        region_id,
943        last_version
944    ))]
945    NoCheckpoint {
946        region_id: RegionId,
947        last_version: ManifestVersion,
948        #[snafu(implicit)]
949        location: Location,
950    },
951
952    #[snafu(display(
953        "No manifests found in range: [{}..{}), region: {}, last_version: {}",
954        start_version,
955        end_version,
956        region_id,
957        last_version
958    ))]
959    NoManifests {
960        region_id: RegionId,
961        start_version: ManifestVersion,
962        end_version: ManifestVersion,
963        last_version: ManifestVersion,
964        #[snafu(implicit)]
965        location: Location,
966    },
967
968    #[snafu(display(
969        "Failed to install manifest to {}, region: {}, available manifest version: {}, last version: {}",
970        target_version,
971        region_id,
972        available_version,
973        last_version
974    ))]
975    InstallManifestTo {
976        region_id: RegionId,
977        target_version: ManifestVersion,
978        available_version: ManifestVersion,
979        #[snafu(implicit)]
980        location: Location,
981        last_version: ManifestVersion,
982    },
983
984    #[snafu(display("Region {} is stopped", region_id))]
985    RegionStopped {
986        region_id: RegionId,
987        #[snafu(implicit)]
988        location: Location,
989    },
990
991    #[snafu(display(
992        "Time range predicate overflows, timestamp: {:?}, target unit: {}",
993        timestamp,
994        unit
995    ))]
996    TimeRangePredicateOverflow {
997        timestamp: Timestamp,
998        unit: TimeUnit,
999        #[snafu(implicit)]
1000        location: Location,
1001    },
1002
1003    #[snafu(display("Failed to open region"))]
1004    OpenRegion {
1005        #[snafu(implicit)]
1006        location: Location,
1007        source: Arc<Error>,
1008    },
1009
1010    #[snafu(display(
1011        "Region {} does not satisfy requirement '{}': {}",
1012        region_id,
1013        requirement,
1014        reason
1015    ))]
1016    RegionRequirement {
1017        region_id: RegionId,
1018        requirement: &'static str,
1019        reason: &'static str,
1020        #[snafu(implicit)]
1021        location: Location,
1022    },
1023
1024    #[snafu(display("Failed to parse job id"))]
1025    ParseJobId {
1026        #[snafu(implicit)]
1027        location: Location,
1028        #[snafu(source)]
1029        error: uuid::Error,
1030    },
1031
1032    #[snafu(display("Operation is not supported: {}", err_msg))]
1033    UnsupportedOperation {
1034        err_msg: String,
1035        #[snafu(implicit)]
1036        location: Location,
1037    },
1038
1039    #[snafu(display(
1040        "Failed to remotely compact region {} by job {:?} due to {}",
1041        region_id,
1042        job_id,
1043        reason
1044    ))]
1045    RemoteCompaction {
1046        region_id: RegionId,
1047        job_id: Option<JobId>,
1048        reason: String,
1049        #[snafu(implicit)]
1050        location: Location,
1051    },
1052
1053    #[snafu(display("Failed to initialize puffin stager"))]
1054    PuffinInitStager {
1055        source: puffin::error::Error,
1056        #[snafu(implicit)]
1057        location: Location,
1058    },
1059
1060    #[snafu(display("Failed to purge puffin stager"))]
1061    PuffinPurgeStager {
1062        source: puffin::error::Error,
1063        #[snafu(implicit)]
1064        location: Location,
1065    },
1066
1067    #[snafu(display("Failed to build puffin reader"))]
1068    PuffinBuildReader {
1069        source: puffin::error::Error,
1070        #[snafu(implicit)]
1071        location: Location,
1072    },
1073
1074    #[snafu(display("Failed to retrieve index options from column metadata"))]
1075    IndexOptions {
1076        #[snafu(implicit)]
1077        location: Location,
1078        source: datatypes::error::Error,
1079        column_name: String,
1080    },
1081
1082    #[snafu(display("Failed to create fulltext index creator"))]
1083    CreateFulltextCreator {
1084        source: index::fulltext_index::error::Error,
1085        #[snafu(implicit)]
1086        location: Location,
1087    },
1088
1089    #[snafu(display("Failed to cast vector of {from} to {to}"))]
1090    CastVector {
1091        #[snafu(implicit)]
1092        location: Location,
1093        from: ConcreteDataType,
1094        to: ConcreteDataType,
1095        source: datatypes::error::Error,
1096    },
1097
1098    #[snafu(display("Failed to push text to fulltext index"))]
1099    FulltextPushText {
1100        source: index::fulltext_index::error::Error,
1101        #[snafu(implicit)]
1102        location: Location,
1103    },
1104
1105    #[snafu(display("Failed to finalize fulltext index creator"))]
1106    FulltextFinish {
1107        source: index::fulltext_index::error::Error,
1108        #[snafu(implicit)]
1109        location: Location,
1110    },
1111
1112    #[snafu(display("Failed to apply fulltext index"))]
1113    ApplyFulltextIndex {
1114        source: index::fulltext_index::error::Error,
1115        #[snafu(implicit)]
1116        location: Location,
1117    },
1118
1119    #[snafu(display("SST file {} does not contain valid stats info", file_path))]
1120    StatsNotPresent {
1121        file_path: String,
1122        #[snafu(implicit)]
1123        location: Location,
1124    },
1125
1126    #[snafu(display("Failed to decode stats of file {}", file_path))]
1127    DecodeStats {
1128        file_path: String,
1129        #[snafu(implicit)]
1130        location: Location,
1131    },
1132
1133    #[snafu(display("Invalid SST primary key range: {reason}"))]
1134    InvalidPrimaryKeyRange {
1135        reason: String,
1136        #[snafu(implicit)]
1137        location: Location,
1138    },
1139
1140    #[snafu(display("Failed to decode SST primary key range {endpoint} endpoint"))]
1141    DecodePrimaryKeyRange {
1142        endpoint: &'static str,
1143        source: mito_codec::error::Error,
1144        #[snafu(implicit)]
1145        location: Location,
1146    },
1147
1148    #[snafu(display("Region {} is busy", region_id))]
1149    RegionBusy {
1150        region_id: RegionId,
1151        #[snafu(implicit)]
1152        location: Location,
1153    },
1154
1155    #[snafu(display("Failed to get schema metadata"))]
1156    GetSchemaMetadata {
1157        source: common_meta::error::Error,
1158        #[snafu(implicit)]
1159        location: Location,
1160    },
1161
1162    #[snafu(display("Timeout"))]
1163    Timeout {
1164        #[snafu(source)]
1165        error: Elapsed,
1166        #[snafu(implicit)]
1167        location: Location,
1168    },
1169
1170    #[snafu(display("Failed to read file metadata"))]
1171    Metadata {
1172        #[snafu(source)]
1173        error: std::io::Error,
1174        #[snafu(implicit)]
1175        location: Location,
1176    },
1177
1178    #[snafu(display("Failed to push value to bloom filter"))]
1179    PushBloomFilterValue {
1180        source: index::bloom_filter::error::Error,
1181        #[snafu(implicit)]
1182        location: Location,
1183    },
1184
1185    #[snafu(display("Failed to finish bloom filter"))]
1186    BloomFilterFinish {
1187        source: index::bloom_filter::error::Error,
1188        #[snafu(implicit)]
1189        location: Location,
1190    },
1191
1192    #[snafu(display("Manual compaction is override by following operations."))]
1193    ManualCompactionOverride {},
1194
1195    #[snafu(display("Manual compaction is already running for region {region_id}."))]
1196    ManualCompactionAlreadyRunning { region_id: RegionId },
1197
1198    #[snafu(display("Compaction is cancelled."))]
1199    CompactionCancelled {},
1200
1201    #[snafu(display("Flush is cancelled."))]
1202    FlushCancelled {},
1203
1204    #[snafu(display("Compaction memory exhausted for region {region_id} (policy: {policy})",))]
1205    CompactionMemoryExhausted {
1206        region_id: RegionId,
1207        policy: String,
1208        #[snafu(source)]
1209        source: common_memory_manager::Error,
1210        #[snafu(implicit)]
1211        location: Location,
1212    },
1213
1214    #[snafu(display(
1215        "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: {}",
1216        global,
1217        region
1218    ))]
1219    IncompatibleWalProviderChange { global: String, region: String },
1220
1221    #[snafu(display("Expected mito manifest info"))]
1222    MitoManifestInfo {
1223        #[snafu(implicit)]
1224        location: Location,
1225    },
1226
1227    #[snafu(display("Failed to scan series"))]
1228    ScanSeries {
1229        #[snafu(implicit)]
1230        location: Location,
1231        source: Arc<Error>,
1232    },
1233
1234    #[snafu(display("Partition {} scan multiple times", partition))]
1235    ScanMultiTimes {
1236        partition: usize,
1237        #[snafu(implicit)]
1238        location: Location,
1239    },
1240
1241    #[snafu(display("Invalid partition expression: {}", expr))]
1242    InvalidPartitionExpr {
1243        expr: String,
1244        #[snafu(implicit)]
1245        location: Location,
1246        source: partition::error::Error,
1247    },
1248
1249    #[snafu(display("Failed to decode bulk wal entry"))]
1250    ConvertBulkWalEntry {
1251        #[snafu(implicit)]
1252        location: Location,
1253        source: common_grpc::Error,
1254    },
1255
1256    #[snafu(display("Failed to encode"))]
1257    Encode {
1258        #[snafu(implicit)]
1259        location: Location,
1260        source: mito_codec::error::Error,
1261    },
1262
1263    #[snafu(display("Failed to decode"))]
1264    Decode {
1265        #[snafu(implicit)]
1266        location: Location,
1267        source: mito_codec::error::Error,
1268    },
1269
1270    #[snafu(display("Unexpected: {reason}"))]
1271    Unexpected {
1272        reason: String,
1273        #[snafu(implicit)]
1274        location: Location,
1275    },
1276
1277    #[cfg(feature = "enterprise")]
1278    #[snafu(display("Failed to scan external range"))]
1279    ScanExternalRange {
1280        source: BoxedError,
1281        #[snafu(implicit)]
1282        location: Location,
1283    },
1284
1285    #[snafu(display(
1286        "Inconsistent timestamp column length, expect: {}, actual: {}",
1287        expected,
1288        actual
1289    ))]
1290    InconsistentTimestampLength {
1291        expected: usize,
1292        actual: usize,
1293        #[snafu(implicit)]
1294        location: Location,
1295    },
1296
1297    #[snafu(display(
1298        "Too many files to read concurrently: {}, max allowed: {}",
1299        actual,
1300        max
1301    ))]
1302    TooManyFilesToRead {
1303        actual: usize,
1304        max: usize,
1305        #[snafu(implicit)]
1306        location: Location,
1307    },
1308
1309    #[snafu(display("Duration out of range: {input:?}"))]
1310    DurationOutOfRange {
1311        input: std::time::Duration,
1312        #[snafu(source)]
1313        error: chrono::OutOfRangeError,
1314        #[snafu(implicit)]
1315        location: Location,
1316    },
1317
1318    #[snafu(display("GC job permit exhausted"))]
1319    TooManyGcJobs {
1320        #[snafu(implicit)]
1321        location: Location,
1322    },
1323
1324    #[snafu(display(
1325        "Staging partition expr mismatch, manifest: {:?}, request: {}",
1326        manifest_expr,
1327        request_expr
1328    ))]
1329    StagingPartitionExprMismatch {
1330        manifest_expr: Option<String>,
1331        request_expr: String,
1332        #[snafu(implicit)]
1333        location: Location,
1334    },
1335
1336    #[snafu(display(
1337        "Invalid source and target region, source: {}, target: {}",
1338        source_region_id,
1339        target_region_id
1340    ))]
1341    InvalidSourceAndTargetRegion {
1342        source_region_id: RegionId,
1343        target_region_id: RegionId,
1344        #[snafu(implicit)]
1345        location: Location,
1346    },
1347
1348    #[snafu(display("Failed to prune file"))]
1349    PruneFile {
1350        source: Arc<Error>,
1351        #[snafu(implicit)]
1352        location: Location,
1353    },
1354
1355    #[snafu(display("Failed to cast column"))]
1356    CastColumn {
1357        #[snafu(source)]
1358        error: datafusion::error::DataFusionError,
1359        #[snafu(implicit)]
1360        location: Location,
1361    },
1362
1363    #[snafu(display("Failed to generate Arrow schema from Parquet file: {}", file))]
1364    ParquetToArrowSchema {
1365        file: String,
1366        #[snafu(source)]
1367        error: parquet::errors::ParquetError,
1368        #[snafu(implicit)]
1369        location: Location,
1370    },
1371
1372    #[snafu(display(
1373        "Region {} is in {:?} state, expect: Writable, Staging or Downgrading",
1374        region_id,
1375        state
1376    ))]
1377    FlushableRegionState {
1378        region_id: RegionId,
1379        state: RegionRoleState,
1380        #[snafu(implicit)]
1381        location: Location,
1382    },
1383}
1384
1385pub type Result<T, E = Error> = std::result::Result<T, E>;
1386
1387impl Error {
1388    /// Returns true if we need to fill default value for a region.
1389    pub(crate) fn is_fill_default(&self) -> bool {
1390        matches!(self, Error::FillDefault { .. })
1391    }
1392
1393    /// Returns true if the file is not found on the object store.
1394    pub(crate) fn is_object_not_found(&self) -> bool {
1395        match self {
1396            Error::OpenDal { error, .. } => error.kind() == ErrorKind::NotFound,
1397            Error::ManifestDeltaNotFound { .. } => true,
1398            _ => false,
1399        }
1400    }
1401
1402    /// Returns whether a failed manifest update may have been persisted.
1403    ///
1404    /// Unknown errors are treated conservatively because deleting output SSTs after an ambiguous
1405    /// manifest write could leave the manifest referencing missing files.
1406    pub(crate) fn may_have_persisted_manifest_update(&self) -> bool {
1407        match self {
1408            Error::UpdateManifest { .. }
1409            | Error::RegionState { .. }
1410            | Error::RegionTruncated { .. }
1411            | Error::RegionStopped { .. }
1412            | Error::SerdeJson { .. }
1413            | Error::CompressObject { .. } => false,
1414            Error::OpenDal { error, .. } => !matches!(
1415                error.kind(),
1416                ErrorKind::Unsupported
1417                    | ErrorKind::ConfigInvalid
1418                    | ErrorKind::NotFound
1419                    | ErrorKind::PermissionDenied
1420                    | ErrorKind::IsADirectory
1421                    | ErrorKind::NotADirectory
1422                    | ErrorKind::AlreadyExists
1423                    | ErrorKind::RateLimited
1424                    | ErrorKind::IsSameFile
1425                    | ErrorKind::ConditionNotMatch
1426                    | ErrorKind::RangeNotSatisfied
1427            ),
1428            _ => true,
1429        }
1430    }
1431}
1432
1433impl ErrorExt for Error {
1434    fn status_code(&self) -> StatusCode {
1435        use Error::*;
1436
1437        match self {
1438            DataTypeMismatch { source, .. } => source.status_code(),
1439            OpenDal { .. } | ManifestDeltaNotFound { .. } | ReadParquet { .. } => {
1440                StatusCode::StorageUnavailable
1441            }
1442            WriteWal { source, .. } | ReadWal { source, .. } | DeleteWal { source, .. } => {
1443                source.status_code()
1444            }
1445            CompressObject { .. }
1446            | DecompressObject { .. }
1447            | SerdeJson { .. }
1448            | Utf8 { .. }
1449            | NewRecordBatch { .. }
1450            | RegionCorrupted { .. }
1451            | InconsistentFile { .. }
1452            | CreateDefault { .. }
1453            | InvalidParquet { .. }
1454            | OperateAbortedIndex { .. }
1455            | IndexEncodeNull { .. }
1456            | NoCheckpoint { .. }
1457            | NoManifests { .. }
1458            | FilesLost { .. }
1459            | InstallManifestTo { .. }
1460            | Unexpected { .. }
1461            | SerializeColumnMetadata { .. }
1462            | SerializeManifest { .. }
1463            | StagingPartitionExprMismatch { .. } => StatusCode::Unexpected,
1464
1465            RegionNotFound { .. } => StatusCode::RegionNotFound,
1466            ObjectStoreNotFound { .. }
1467            | InvalidScanIndex { .. }
1468            | InvalidMeta { .. }
1469            | InvalidRequest { .. }
1470            | PartitionExprVersionMismatch { .. }
1471            | FillDefault { .. }
1472            | ConvertColumnDataType { .. }
1473            | ColumnNotFound { .. }
1474            | InvalidMetadata { .. }
1475            | InvalidRegionOptions { .. }
1476            | InvalidWalReadRequest { .. }
1477            | PartitionOutOfRange { .. }
1478            | ParseJobId { .. }
1479            | DurationOutOfRange { .. }
1480            | MissingOldManifest { .. }
1481            | MissingNewManifest { .. }
1482            | MissingManifest { .. }
1483            | NoOldManifests { .. }
1484            | MissingPartitionExpr { .. }
1485            | SerializePartitionExpr { .. }
1486            | InvalidSourceAndTargetRegion { .. } => StatusCode::InvalidArguments,
1487
1488            IncrementalQueryStale { .. } | SnapshotFenceStale { .. } => StatusCode::RequestOutdated,
1489
1490            SequenceRangeUnsupported { .. } => StatusCode::Unsupported,
1491
1492            RegionSequenceDomainBroken { .. }
1493            | RegionMetadataNotFound { .. }
1494            | Join { .. }
1495            | WorkerStopped { .. }
1496            | Recv { .. }
1497            | DecodeWal { .. }
1498            | ComputeArrow { .. }
1499            | EvalPartitionFilter { .. }
1500            | MergeCandidateSeries { .. }
1501            | BiErrors { .. }
1502            | StopScheduler { .. }
1503            | ComputeVector { .. }
1504            | EncodeMemtable { .. }
1505            | CreateDir { .. }
1506            | ReadDataPart { .. }
1507            | BuildEntry { .. }
1508            | Metadata { .. }
1509            | CastColumn { .. }
1510            | MitoManifestInfo { .. }
1511            | ParquetToArrowSchema { .. } => StatusCode::Internal,
1512
1513            FetchManifests { source, .. } => source.status_code(),
1514
1515            OpenRegion { source, .. } => source.status_code(),
1516
1517            WriteParquet { .. } => StatusCode::StorageUnavailable,
1518            WriteGroup { source, .. } => source.status_code(),
1519            InvalidBatch { .. } => StatusCode::InvalidArguments,
1520            InvalidRecordBatch { .. } => StatusCode::InvalidArguments,
1521            ConvertVector { source, .. } => source.status_code(),
1522
1523            PrimaryKeyLengthMismatch { .. } => StatusCode::InvalidArguments,
1524            InvalidSender { .. } => StatusCode::InvalidArguments,
1525            InvalidSchedulerState { .. } => StatusCode::InvalidArguments,
1526            RegionRequirement { .. } => StatusCode::InvalidArguments,
1527            DeleteSsts { .. } | DeleteIndex { .. } | DeleteIndexes { .. } => {
1528                StatusCode::StorageUnavailable
1529            }
1530            FlushRegion { source, .. } | BuildIndexAsync { source, .. } => source.status_code(),
1531            RegionDropped { .. } => StatusCode::Cancelled,
1532            RegionClosed { .. } => StatusCode::Cancelled,
1533            StaleCompactionExecution { .. } => StatusCode::Cancelled,
1534            RegionTruncated { .. } => StatusCode::Cancelled,
1535            RejectWrite { .. } => StatusCode::StorageUnavailable,
1536            CompactRegion { source, .. } => source.status_code(),
1537            EditRegion { source, .. } => source.status_code(),
1538            CompatReader { .. } => StatusCode::Unexpected,
1539            InvalidRegionRequest { source, .. } => source.status_code(),
1540            RegionState { .. } | UpdateManifest { .. } => StatusCode::RegionNotReady,
1541            JsonOptions { .. } => StatusCode::InvalidArguments,
1542            EmptyRegionDir { .. } | EmptyManifestDir { .. } => StatusCode::RegionNotFound,
1543            ConvertValue { source, .. } => source.status_code(),
1544            ApplyBloomFilterIndex { source, .. } => source.status_code(),
1545            InvalidPartitionExpr { source, .. } => source.status_code(),
1546            BuildIndexApplier { source, .. }
1547            | PushIndexValue { source, .. }
1548            | ApplyInvertedIndex { source, .. }
1549            | IndexFinish { source, .. } => source.status_code(),
1550            PuffinReadBlob { source, .. }
1551            | PuffinAddBlob { source, .. }
1552            | PuffinInitStager { source, .. }
1553            | PuffinBuildReader { source, .. }
1554            | PuffinPurgeStager { source, .. } => source.status_code(),
1555            CleanDir { .. } => StatusCode::Unexpected,
1556            InvalidConfig { .. } => StatusCode::InvalidArguments,
1557            StaleLogEntry { .. }
1558            | InvalidNativeHistogramSubfield { .. }
1559            | InvalidNativeHistogramFieldId { .. } => StatusCode::Unexpected,
1560
1561            External { source, .. } => source.status_code(),
1562
1563            RecordBatch { source, .. } => source.status_code(),
1564
1565            Download { .. } | Upload { .. } => StatusCode::StorageUnavailable,
1566            ChecksumMismatch { .. } => StatusCode::Unexpected,
1567            RegionStopped { .. } => StatusCode::RegionNotReady,
1568            TimeRangePredicateOverflow { .. } => StatusCode::InvalidArguments,
1569            UnsupportedOperation { .. } => StatusCode::Unsupported,
1570            RemoteCompaction { .. } => StatusCode::Unexpected,
1571
1572            IndexOptions { source, .. } => source.status_code(),
1573            CreateFulltextCreator { source, .. } => source.status_code(),
1574            CastVector { source, .. } => source.status_code(),
1575            FulltextPushText { source, .. }
1576            | FulltextFinish { source, .. }
1577            | ApplyFulltextIndex { source, .. } => source.status_code(),
1578            DecodeStats { .. }
1579            | StatsNotPresent { .. }
1580            | InvalidPrimaryKeyRange { .. }
1581            | DecodePrimaryKeyRange { .. } => StatusCode::Internal,
1582            RegionBusy { .. } => StatusCode::RegionBusy,
1583            GetSchemaMetadata { source, .. } => source.status_code(),
1584            Timeout { .. } => StatusCode::Cancelled,
1585
1586            DecodeArrowRowGroup { .. } => StatusCode::Internal,
1587
1588            PushBloomFilterValue { source, .. } | BloomFilterFinish { source, .. } => {
1589                source.status_code()
1590            }
1591
1592            ManualCompactionOverride {} | CompactionCancelled {} | FlushCancelled {} => {
1593                StatusCode::Cancelled
1594            }
1595
1596            // A concurrent manual compaction fails fast instead of being queued;
1597            // the conflict is reported to the caller, which decides whether to
1598            // issue a new request after the running one finishes.
1599            ManualCompactionAlreadyRunning { .. } => StatusCode::RegionBusy,
1600
1601            CompactionMemoryExhausted { source, .. } => source.status_code(),
1602
1603            IncompatibleWalProviderChange { .. } => StatusCode::InvalidArguments,
1604
1605            ScanSeries { source, .. } => source.status_code(),
1606
1607            ScanMultiTimes { .. } => StatusCode::InvalidArguments,
1608            ConvertBulkWalEntry { source, .. } => source.status_code(),
1609
1610            Encode { source, .. } | Decode { source, .. } => source.status_code(),
1611
1612            #[cfg(feature = "enterprise")]
1613            ScanExternalRange { source, .. } => source.status_code(),
1614
1615            InconsistentTimestampLength { .. } => StatusCode::InvalidArguments,
1616
1617            TooManyFilesToRead { .. } | TooManyGcJobs { .. } => StatusCode::RateLimited,
1618
1619            PruneFile { source, .. } => source.status_code(),
1620
1621            FlushableRegionState { .. } => StatusCode::RegionNotReady,
1622        }
1623    }
1624
1625    fn as_any(&self) -> &dyn Any {
1626        self
1627    }
1628
1629    fn retry_hint(&self) -> RetryHint {
1630        use Error::*;
1631
1632        match self {
1633            ReadParquet { .. }
1634            | WriteParquet { .. }
1635            | RejectWrite { .. }
1636            | Download { .. }
1637            | Upload { .. }
1638            | RegionState { .. }
1639            | UpdateManifest { .. }
1640            | RegionStopped { .. }
1641            | RegionBusy { .. }
1642            | ManualCompactionAlreadyRunning { .. }
1643            | FlushableRegionState { .. }
1644            | ManifestDeltaNotFound { .. } => RetryHint::Retryable,
1645
1646            OpenDal { error, .. }
1647            | DeleteSsts { error, .. }
1648            | DeleteIndex { error, .. }
1649            | DeleteIndexes { error, .. } => retry_hint_from_opendal_error(error),
1650
1651            WriteWal { source, .. }
1652            | ReadWal { source, .. }
1653            | DeleteWal { source, .. }
1654            | FetchManifests { source, .. }
1655            | External { source, .. } => source.retry_hint(),
1656
1657            OpenRegion { source, .. }
1658            | WriteGroup { source, .. }
1659            | FlushRegion { source, .. }
1660            | BuildIndexAsync { source, .. }
1661            | CompactRegion { source, .. }
1662            | EditRegion { source, .. }
1663            | ScanSeries { source, .. }
1664            | PruneFile { source, .. } => source.retry_hint(),
1665
1666            DataTypeMismatch { source, .. }
1667            | ConvertVector { source, .. }
1668            | ConvertValue { source, .. }
1669            | IndexOptions { source, .. }
1670            | CastVector { source, .. } => source.retry_hint(),
1671
1672            BuildIndexApplier { source, .. }
1673            | PushIndexValue { source, .. }
1674            | ApplyInvertedIndex { source, .. }
1675            | IndexFinish { source, .. } => source.retry_hint(),
1676
1677            ApplyBloomFilterIndex { source, .. }
1678            | PushBloomFilterValue { source, .. }
1679            | BloomFilterFinish { source, .. } => source.retry_hint(),
1680
1681            PuffinReadBlob { source, .. }
1682            | PuffinAddBlob { source, .. }
1683            | PuffinInitStager { source, .. }
1684            | PuffinBuildReader { source, .. }
1685            | PuffinPurgeStager { source, .. } => source.retry_hint(),
1686
1687            CreateFulltextCreator { source, .. }
1688            | FulltextPushText { source, .. }
1689            | FulltextFinish { source, .. }
1690            | ApplyFulltextIndex { source, .. } => source.retry_hint(),
1691
1692            InvalidRegionRequest { source, .. } => source.retry_hint(),
1693            InvalidPartitionExpr { source, .. } => source.retry_hint(),
1694            RecordBatch { source, .. } => source.retry_hint(),
1695            GetSchemaMetadata { source, .. } => source.retry_hint(),
1696            CompactionMemoryExhausted { source, .. } => source.retry_hint(),
1697            ConvertBulkWalEntry { source, .. } => source.retry_hint(),
1698            Encode { source, .. } | Decode { source, .. } => source.retry_hint(),
1699
1700            #[cfg(feature = "enterprise")]
1701            ScanExternalRange { source, .. } => source.retry_hint(),
1702
1703            _ => RetryHint::NonRetryable,
1704        }
1705    }
1706}
1707
1708#[cfg(test)]
1709mod tests {
1710    use snafu::IntoError;
1711
1712    use super::*;
1713
1714    #[test]
1715    fn test_manifest_update_persistence() {
1716        let rejected_kinds = [
1717            ErrorKind::Unsupported,
1718            ErrorKind::ConfigInvalid,
1719            ErrorKind::NotFound,
1720            ErrorKind::PermissionDenied,
1721            ErrorKind::IsADirectory,
1722            ErrorKind::NotADirectory,
1723            ErrorKind::AlreadyExists,
1724            ErrorKind::RateLimited,
1725            ErrorKind::IsSameFile,
1726            ErrorKind::ConditionNotMatch,
1727            ErrorKind::RangeNotSatisfied,
1728        ];
1729        for kind in rejected_kinds {
1730            let error = OpenDalSnafu {}.into_error(object_store::Error::new(kind, "test"));
1731            assert!(
1732                !error.may_have_persisted_manifest_update(),
1733                "error kind {kind:?} should prove the manifest was not persisted"
1734            );
1735        }
1736
1737        let error =
1738            OpenDalSnafu {}.into_error(object_store::Error::new(ErrorKind::Unexpected, "test"));
1739        assert!(error.may_have_persisted_manifest_update());
1740
1741        let region_id = RegionId::new(1, 1);
1742        let error = RegionTruncatedSnafu { region_id }.build();
1743        assert!(!error.may_have_persisted_manifest_update());
1744
1745        // This can be raised while applying an edit after its manifest file was saved.
1746        let error = RegionMetadataNotFoundSnafu {}.build();
1747        assert!(error.may_have_persisted_manifest_update());
1748    }
1749}