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