1use std::str::Utf8Error;
16use std::sync::Arc;
17
18use common_error::ext::{BoxedError, ErrorExt, RetryHint};
19use common_error::status_code::StatusCode;
20use common_macro::stack_trace_debug;
21use common_procedure::ProcedureId;
22use common_wal::kafka::rskafka_client_error_to_retry_hint;
23use object_store::error::retry_hint_from_opendal_error;
24use serde_json::error::Error as JsonError;
25use snafu::{Location, Snafu};
26use store_api::storage::RegionId;
27use table::metadata::TableId;
28
29use crate::DatanodeId;
30use crate::peer::Peer;
31
32#[derive(Snafu)]
33#[snafu(visibility(pub))]
34#[stack_trace_debug]
35pub enum Error {
36 #[snafu(display("Empty key is not allowed"))]
37 EmptyKey {
38 #[snafu(implicit)]
39 location: Location,
40 },
41
42 #[snafu(display(
43 "Another procedure is operating the region: {} on peer: {}",
44 region_id,
45 peer_id
46 ))]
47 RegionOperatingRace {
48 #[snafu(implicit)]
49 location: Location,
50 peer_id: DatanodeId,
51 region_id: RegionId,
52 },
53
54 #[snafu(display("Failed to connect to Etcd"))]
55 ConnectEtcd {
56 #[snafu(source)]
57 error: etcd_client::Error,
58 #[snafu(implicit)]
59 location: Location,
60 },
61
62 #[snafu(display("Failed to execute via Etcd"))]
63 EtcdFailed {
64 #[snafu(source)]
65 error: etcd_client::Error,
66 #[snafu(implicit)]
67 location: Location,
68 },
69
70 #[snafu(display("Failed to execute {} txn operations via Etcd", max_operations))]
71 EtcdTxnFailed {
72 max_operations: usize,
73 #[snafu(source)]
74 error: etcd_client::Error,
75 #[snafu(implicit)]
76 location: Location,
77 },
78
79 #[snafu(display("Failed to get sequence: {}", err_msg))]
80 NextSequence {
81 err_msg: String,
82 #[snafu(implicit)]
83 location: Location,
84 },
85
86 #[snafu(display("Unexpected sequence value: {}", err_msg))]
87 UnexpectedSequenceValue {
88 err_msg: String,
89 #[snafu(implicit)]
90 location: Location,
91 },
92
93 #[snafu(display("Table info not found: {}", table))]
94 TableInfoNotFound {
95 table: String,
96 #[snafu(implicit)]
97 location: Location,
98 },
99
100 #[snafu(display("Failed to register procedure loader, type name: {}", type_name))]
101 RegisterProcedureLoader {
102 type_name: String,
103 #[snafu(implicit)]
104 location: Location,
105 source: common_procedure::error::Error,
106 },
107
108 #[snafu(display("Failed to register repartition procedure loader"))]
109 RegisterRepartitionProcedureLoader {
110 #[snafu(implicit)]
111 location: Location,
112 source: BoxedError,
113 },
114
115 #[snafu(display("Failed to create repartition procedure"))]
116 CreateRepartitionProcedure {
117 source: BoxedError,
118 #[snafu(implicit)]
119 location: Location,
120 },
121
122 #[snafu(display("Failed to submit procedure"))]
123 SubmitProcedure {
124 #[snafu(implicit)]
125 location: Location,
126 source: common_procedure::Error,
127 },
128
129 #[snafu(display("Failed to query procedure"))]
130 QueryProcedure {
131 #[snafu(implicit)]
132 location: Location,
133 source: common_procedure::Error,
134 },
135
136 #[snafu(display("Procedure not found: {pid}"))]
137 ProcedureNotFound {
138 #[snafu(implicit)]
139 location: Location,
140 pid: String,
141 },
142
143 #[snafu(display("Failed to parse procedure id: {key}"))]
144 ParseProcedureId {
145 #[snafu(implicit)]
146 location: Location,
147 key: String,
148 #[snafu(source)]
149 error: common_procedure::ParseIdError,
150 },
151
152 #[snafu(display("Unsupported operation {}", operation))]
153 Unsupported {
154 operation: String,
155 #[snafu(implicit)]
156 location: Location,
157 },
158
159 #[snafu(display("Trying to write to a read-only kv backend: {}", name))]
160 ReadOnlyKvBackend {
161 name: String,
162 #[snafu(implicit)]
163 location: Location,
164 },
165
166 #[snafu(display("Failed to get procedure state receiver, procedure id: {procedure_id}"))]
167 ProcedureStateReceiver {
168 procedure_id: ProcedureId,
169 #[snafu(implicit)]
170 location: Location,
171 source: common_procedure::Error,
172 },
173
174 #[snafu(display("Procedure state receiver not found: {procedure_id}"))]
175 ProcedureStateReceiverNotFound {
176 procedure_id: ProcedureId,
177 #[snafu(implicit)]
178 location: Location,
179 },
180
181 #[snafu(display("Failed to wait procedure done"))]
182 WaitProcedure {
183 #[snafu(implicit)]
184 location: Location,
185 source: common_procedure::Error,
186 },
187
188 #[snafu(display("Failed to start procedure manager"))]
189 StartProcedureManager {
190 #[snafu(implicit)]
191 location: Location,
192 source: common_procedure::Error,
193 },
194
195 #[snafu(display("Failed to stop procedure manager"))]
196 StopProcedureManager {
197 #[snafu(implicit)]
198 location: Location,
199 source: common_procedure::Error,
200 },
201
202 #[snafu(display(
203 "Failed to get procedure output, procedure id: {procedure_id}, error: {err_msg}"
204 ))]
205 ProcedureOutput {
206 procedure_id: String,
207 err_msg: String,
208 #[snafu(implicit)]
209 location: Location,
210 },
211
212 #[snafu(display("Primary key '{key}' not found when creating region request"))]
213 PrimaryKeyNotFound {
214 key: String,
215 #[snafu(implicit)]
216 location: Location,
217 },
218
219 #[snafu(display("Failed to build table meta for table: {}", table_name))]
220 BuildTableMeta {
221 table_name: String,
222 #[snafu(source)]
223 error: table::metadata::TableMetaBuilderError,
224 #[snafu(implicit)]
225 location: Location,
226 },
227
228 #[snafu(display("Table occurs error"))]
229 Table {
230 #[snafu(implicit)]
231 location: Location,
232 source: table::error::Error,
233 },
234
235 #[snafu(display("Failed to find table route for table id {}", table_id))]
236 TableRouteNotFound {
237 table_id: TableId,
238 #[snafu(implicit)]
239 location: Location,
240 },
241
242 #[snafu(display("Failed to find table repartition metadata for table id {}", table_id))]
243 TableRepartNotFound {
244 table_id: TableId,
245 #[snafu(implicit)]
246 location: Location,
247 },
248
249 #[snafu(display("Failed to decode protobuf"))]
250 DecodeProto {
251 #[snafu(implicit)]
252 location: Location,
253 #[snafu(source)]
254 error: prost::DecodeError,
255 },
256
257 #[snafu(display("Failed to encode object into json"))]
258 EncodeJson {
259 #[snafu(implicit)]
260 location: Location,
261 #[snafu(source)]
262 error: JsonError,
263 },
264
265 #[snafu(display("Failed to decode object from json"))]
266 DecodeJson {
267 #[snafu(implicit)]
268 location: Location,
269 #[snafu(source)]
270 error: JsonError,
271 },
272
273 #[snafu(display("Failed to serialize to json: {}", input))]
274 SerializeToJson {
275 input: String,
276 #[snafu(source)]
277 error: serde_json::error::Error,
278 #[snafu(implicit)]
279 location: Location,
280 },
281
282 #[snafu(display("Failed to deserialize from json: {}", input))]
283 DeserializeFromJson {
284 input: String,
285 #[snafu(source)]
286 error: serde_json::error::Error,
287 #[snafu(implicit)]
288 location: Location,
289 },
290
291 #[snafu(display("Payload not exist"))]
292 PayloadNotExist {
293 #[snafu(implicit)]
294 location: Location,
295 },
296
297 #[snafu(display("Failed to serde json"))]
298 SerdeJson {
299 #[snafu(source)]
300 error: serde_json::error::Error,
301 #[snafu(implicit)]
302 location: Location,
303 },
304
305 #[snafu(display("Failed to parse value {} into key {}", value, key))]
306 ParseOption {
307 key: String,
308 value: String,
309 #[snafu(implicit)]
310 location: Location,
311 },
312
313 #[snafu(display("Corrupted table route data, err: {}", err_msg))]
314 RouteInfoCorrupted {
315 err_msg: String,
316 #[snafu(implicit)]
317 location: Location,
318 },
319
320 #[snafu(display("Illegal state from server, code: {}, error: {}", code, err_msg))]
321 IllegalServerState {
322 code: i32,
323 err_msg: String,
324 #[snafu(implicit)]
325 location: Location,
326 },
327
328 #[snafu(display("Failed to convert alter table request"))]
329 ConvertAlterTableRequest {
330 source: common_grpc_expr::error::Error,
331 #[snafu(implicit)]
332 location: Location,
333 },
334
335 #[snafu(display("Invalid protobuf message: {err_msg}"))]
336 InvalidProtoMsg {
337 err_msg: String,
338 #[snafu(implicit)]
339 location: Location,
340 },
341
342 #[snafu(display("Unexpected: {err_msg}"))]
343 Unexpected {
344 err_msg: String,
345 #[snafu(implicit)]
346 location: Location,
347 },
348
349 #[snafu(display("Metasrv election has no leader at this moment"))]
350 ElectionNoLeader {
351 #[snafu(implicit)]
352 location: Location,
353 },
354
355 #[snafu(display("Metasrv election leader lease expired"))]
356 ElectionLeaderLeaseExpired {
357 #[snafu(implicit)]
358 location: Location,
359 },
360
361 #[snafu(display("Metasrv election leader lease changed during election"))]
362 ElectionLeaderLeaseChanged {
363 #[snafu(implicit)]
364 location: Location,
365 },
366
367 #[snafu(display("Table already exists, table: {}", table_name))]
368 TableAlreadyExists {
369 table_name: String,
370 #[snafu(implicit)]
371 location: Location,
372 },
373
374 #[snafu(display("View already exists, view: {}", view_name))]
375 ViewAlreadyExists {
376 view_name: String,
377 #[snafu(implicit)]
378 location: Location,
379 },
380
381 #[snafu(display("Flow already exists: {}", flow_name))]
382 FlowAlreadyExists {
383 flow_name: String,
384 #[snafu(implicit)]
385 location: Location,
386 },
387
388 #[snafu(display("Schema already exists, catalog:{}, schema: {}", catalog, schema))]
389 SchemaAlreadyExists {
390 catalog: String,
391 schema: String,
392 #[snafu(implicit)]
393 location: Location,
394 },
395
396 #[snafu(display("Failed to convert raw key to str"))]
397 ConvertRawKey {
398 #[snafu(implicit)]
399 location: Location,
400 #[snafu(source)]
401 error: Utf8Error,
402 },
403
404 #[snafu(display("Table not found: '{}'", table_name))]
405 TableNotFound {
406 table_name: String,
407 #[snafu(implicit)]
408 location: Location,
409 },
410
411 #[snafu(display("Region not found: {}", region_id))]
412 RegionNotFound {
413 region_id: RegionId,
414 #[snafu(implicit)]
415 location: Location,
416 },
417
418 #[snafu(display("View not found: '{}'", view_name))]
419 ViewNotFound {
420 view_name: String,
421 #[snafu(implicit)]
422 location: Location,
423 },
424
425 #[snafu(display("Flow not found: '{}'", flow_name))]
426 FlowNotFound {
427 flow_name: String,
428 #[snafu(implicit)]
429 location: Location,
430 },
431
432 #[snafu(display("Flow route not found: '{}'", flow_name))]
433 FlowRouteNotFound {
434 flow_name: String,
435 #[snafu(implicit)]
436 location: Location,
437 },
438
439 #[snafu(display("Schema nod found, schema: {}", table_schema))]
440 SchemaNotFound {
441 table_schema: String,
442 #[snafu(implicit)]
443 location: Location,
444 },
445
446 #[snafu(display("Catalog not found, catalog: {}", catalog))]
447 CatalogNotFound {
448 catalog: String,
449 #[snafu(implicit)]
450 location: Location,
451 },
452
453 #[snafu(display("Invalid metadata, err: {}", err_msg))]
454 InvalidMetadata {
455 err_msg: String,
456 #[snafu(implicit)]
457 location: Location,
458 },
459
460 #[snafu(display("Invalid view info, err: {}", err_msg))]
461 InvalidViewInfo {
462 err_msg: String,
463 #[snafu(implicit)]
464 location: Location,
465 },
466
467 #[snafu(display("Invalid flow request body: {:?}", body))]
468 InvalidFlowRequestBody {
469 body: Box<Option<api::v1::flow::flow_request::Body>>,
470 #[snafu(implicit)]
471 location: Location,
472 },
473
474 #[snafu(display("Failed to get kv cache, err: {}", err_msg))]
475 GetKvCache { err_msg: String },
476
477 #[snafu(display("Get null from cache, key: {}", key))]
478 CacheNotGet {
479 key: String,
480 #[snafu(implicit)]
481 location: Location,
482 },
483
484 #[snafu(display("Etcd txn error: {err_msg}"))]
485 EtcdTxnOpResponse {
486 err_msg: String,
487 #[snafu(implicit)]
488 location: Location,
489 },
490
491 #[snafu(display("External error"))]
492 External {
493 #[snafu(implicit)]
494 location: Location,
495 source: BoxedError,
496 },
497
498 #[snafu(display("The response exceeded size limit"))]
499 ResponseExceededSizeLimit {
500 #[snafu(implicit)]
501 location: Location,
502 source: BoxedError,
503 },
504
505 #[snafu(display("Invalid heartbeat response"))]
506 InvalidHeartbeatResponse {
507 #[snafu(implicit)]
508 location: Location,
509 },
510
511 #[snafu(display("Failed to operate on datanode: {}", peer))]
512 OperateDatanode {
513 #[snafu(implicit)]
514 location: Location,
515 peer: Peer,
516 source: BoxedError,
517 },
518
519 #[snafu(display("Retry later"))]
520 RetryLater {
521 source: BoxedError,
522 clean_poisons: bool,
523 },
524
525 #[snafu(display("Abort procedure"))]
526 AbortProcedure {
527 #[snafu(implicit)]
528 location: Location,
529 source: BoxedError,
530 clean_poisons: bool,
531 },
532
533 #[snafu(display("Failed to serialize WAL options for region: {region_id}"))]
534 SerializeWalOptions {
535 region_id: RegionId,
536 #[snafu(source)]
537 error: serde_json::Error,
538 #[snafu(implicit)]
539 location: Location,
540 },
541
542 #[snafu(display("Invalid number of topics {}", num_topics))]
543 InvalidNumTopics {
544 num_topics: usize,
545 #[snafu(implicit)]
546 location: Location,
547 },
548
549 #[snafu(display(
550 "Failed to build a Kafka client, broker endpoints: {:?}",
551 broker_endpoints
552 ))]
553 BuildKafkaClient {
554 broker_endpoints: Vec<String>,
555 #[snafu(implicit)]
556 location: Location,
557 #[snafu(source)]
558 error: rskafka::client::error::Error,
559 },
560
561 #[snafu(display("Failed to create TLS Config"))]
562 TlsConfig {
563 #[snafu(implicit)]
564 location: Location,
565 source: common_wal::error::Error,
566 },
567
568 #[snafu(display("Failed to build a Kafka controller client"))]
569 BuildKafkaCtrlClient {
570 #[snafu(implicit)]
571 location: Location,
572 #[snafu(source)]
573 error: rskafka::client::error::Error,
574 },
575
576 #[snafu(display(
577 "Failed to get a Kafka partition client, topic: {}, partition: {}",
578 topic,
579 partition
580 ))]
581 KafkaPartitionClient {
582 topic: String,
583 partition: i32,
584 #[snafu(implicit)]
585 location: Location,
586 #[snafu(source)]
587 error: rskafka::client::error::Error,
588 },
589
590 #[snafu(display(
591 "Failed to get offset from Kafka, topic: {}, partition: {}",
592 topic,
593 partition
594 ))]
595 KafkaGetOffset {
596 topic: String,
597 partition: i32,
598 #[snafu(implicit)]
599 location: Location,
600 #[snafu(source)]
601 error: rskafka::client::error::Error,
602 },
603
604 #[snafu(display("Failed to produce records to Kafka, topic: {}", topic))]
605 ProduceRecord {
606 topic: String,
607 #[snafu(implicit)]
608 location: Location,
609 #[snafu(source)]
610 error: rskafka::client::error::Error,
611 },
612
613 #[snafu(display("Failed to create a Kafka wal topic"))]
614 CreateKafkaWalTopic {
615 #[snafu(implicit)]
616 location: Location,
617 #[snafu(source)]
618 error: rskafka::client::error::Error,
619 },
620
621 #[snafu(display("The topic pool is empty"))]
622 EmptyTopicPool {
623 #[snafu(implicit)]
624 location: Location,
625 },
626
627 #[snafu(display("Unexpected table route type: {}", err_msg))]
628 UnexpectedLogicalRouteTable {
629 #[snafu(implicit)]
630 location: Location,
631 err_msg: String,
632 },
633
634 #[snafu(display("The tasks of {} cannot be empty", name))]
635 EmptyDdlTasks {
636 name: String,
637 #[snafu(implicit)]
638 location: Location,
639 },
640
641 #[snafu(display("Metadata corruption: {}", err_msg))]
642 MetadataCorruption {
643 err_msg: String,
644 #[snafu(implicit)]
645 location: Location,
646 },
647
648 #[snafu(display("Alter logical tables invalid arguments: {}", err_msg))]
649 AlterLogicalTablesInvalidArguments {
650 err_msg: String,
651 #[snafu(implicit)]
652 location: Location,
653 },
654
655 #[snafu(display("Create logical tables invalid arguments: {}", err_msg))]
656 CreateLogicalTablesInvalidArguments {
657 err_msg: String,
658 #[snafu(implicit)]
659 location: Location,
660 },
661
662 #[snafu(display("Invalid node info key: {}", key))]
663 InvalidNodeInfoKey {
664 key: String,
665 #[snafu(implicit)]
666 location: Location,
667 },
668
669 #[snafu(display("Invalid node stat key: {}", key))]
670 InvalidStatKey {
671 key: String,
672 #[snafu(implicit)]
673 location: Location,
674 },
675
676 #[snafu(display("Failed to parse number: {}", err_msg))]
677 ParseNum {
678 err_msg: String,
679 #[snafu(source)]
680 error: std::num::ParseIntError,
681 #[snafu(implicit)]
682 location: Location,
683 },
684
685 #[snafu(display("Invalid role: {}", role))]
686 InvalidRole {
687 role: i32,
688 #[snafu(implicit)]
689 location: Location,
690 },
691
692 #[snafu(display("Invalid set database option, key: {}, value: {}", key, value))]
693 InvalidSetDatabaseOption {
694 key: String,
695 value: String,
696 #[snafu(implicit)]
697 location: Location,
698 },
699
700 #[snafu(display("Invalid unset database option, key: {}", key))]
701 InvalidUnsetDatabaseOption {
702 key: String,
703 #[snafu(implicit)]
704 location: Location,
705 },
706
707 #[snafu(display("Invalid prefix: {}, key: {}", prefix, key))]
708 MismatchPrefix {
709 prefix: String,
710 key: String,
711 #[snafu(implicit)]
712 location: Location,
713 },
714
715 #[snafu(display("Failed to move values: {err_msg}"))]
716 MoveValues {
717 err_msg: String,
718 #[snafu(implicit)]
719 location: Location,
720 },
721
722 #[snafu(display("Failed to parse {} from utf8", name))]
723 FromUtf8 {
724 name: String,
725 #[snafu(source)]
726 error: std::string::FromUtf8Error,
727 #[snafu(implicit)]
728 location: Location,
729 },
730
731 #[snafu(display("Value not exists"))]
732 ValueNotExist {
733 #[snafu(implicit)]
734 location: Location,
735 },
736
737 #[snafu(display("Failed to get cache"))]
738 GetCache { source: Arc<Error> },
739
740 #[snafu(display(
741 "Failed to get latest cache value after {} attempts due to concurrent invalidation",
742 attempts
743 ))]
744 GetLatestCacheRetryExceeded {
745 attempts: usize,
746 #[snafu(implicit)]
747 location: Location,
748 },
749
750 #[cfg(feature = "pg_kvbackend")]
751 #[snafu(display("Failed to execute via Postgres, sql: {}", sql))]
752 PostgresExecution {
753 sql: String,
754 #[snafu(source)]
755 error: tokio_postgres::Error,
756 #[snafu(implicit)]
757 location: Location,
758 },
759
760 #[cfg(feature = "pg_kvbackend")]
761 #[snafu(display("Failed to create connection pool for Postgres"))]
762 CreatePostgresPool {
763 #[snafu(source)]
764 error: deadpool_postgres::CreatePoolError,
765 #[snafu(implicit)]
766 location: Location,
767 },
768
769 #[cfg(feature = "pg_kvbackend")]
770 #[snafu(display("Failed to get Postgres connection from pool: {}", reason))]
771 GetPostgresConnection {
772 reason: String,
773 #[snafu(implicit)]
774 location: Location,
775 },
776
777 #[cfg(feature = "pg_kvbackend")]
778 #[snafu(display("Failed to get Postgres client"))]
779 GetPostgresClient {
780 #[snafu(source)]
781 error: deadpool::managed::PoolError<tokio_postgres::Error>,
782 #[snafu(implicit)]
783 location: Location,
784 },
785
786 #[cfg(feature = "pg_kvbackend")]
787 #[snafu(display("Failed to {} Postgres transaction", operation))]
788 PostgresTransaction {
789 #[snafu(source)]
790 error: tokio_postgres::Error,
791 #[snafu(implicit)]
792 location: Location,
793 operation: String,
794 },
795
796 #[cfg(feature = "pg_kvbackend")]
797 #[snafu(display("Failed to setup PostgreSQL TLS configuration: {}", reason))]
798 PostgresTlsConfig {
799 reason: String,
800 #[snafu(implicit)]
801 location: Location,
802 },
803
804 #[snafu(display("Failed to load TLS certificate from path: {}", path))]
805 LoadTlsCertificate {
806 path: String,
807 #[snafu(source)]
808 error: std::io::Error,
809 #[snafu(implicit)]
810 location: Location,
811 },
812
813 #[cfg(feature = "pg_kvbackend")]
814 #[snafu(display("Invalid TLS configuration: {}", reason))]
815 InvalidTlsConfig {
816 reason: String,
817 #[snafu(implicit)]
818 location: Location,
819 },
820
821 #[cfg(feature = "mysql_kvbackend")]
822 #[snafu(display("Failed to execute via MySql, sql: {}", sql))]
823 MySqlExecution {
824 sql: String,
825 #[snafu(source)]
826 error: sqlx::Error,
827 #[snafu(implicit)]
828 location: Location,
829 },
830
831 #[cfg(feature = "mysql_kvbackend")]
832 #[snafu(display("Failed to create connection pool for MySql"))]
833 CreateMySqlPool {
834 #[snafu(source)]
835 error: sqlx::Error,
836 #[snafu(implicit)]
837 location: Location,
838 },
839
840 #[cfg(feature = "mysql_kvbackend")]
841 #[snafu(display("Failed to decode sql value"))]
842 DecodeSqlValue {
843 #[snafu(source)]
844 error: sqlx::error::Error,
845 #[snafu(implicit)]
846 location: Location,
847 },
848
849 #[cfg(feature = "mysql_kvbackend")]
850 #[snafu(display("Failed to acquire mysql client from pool"))]
851 AcquireMySqlClient {
852 #[snafu(source)]
853 error: sqlx::Error,
854 #[snafu(implicit)]
855 location: Location,
856 },
857
858 #[cfg(feature = "mysql_kvbackend")]
859 #[snafu(display("Failed to {} MySql transaction", operation))]
860 MySqlTransaction {
861 #[snafu(source)]
862 error: sqlx::Error,
863 #[snafu(implicit)]
864 location: Location,
865 operation: String,
866 },
867
868 #[cfg(any(feature = "pg_kvbackend", feature = "mysql_kvbackend"))]
869 #[snafu(display("Rds transaction retry failed"))]
870 RdsTransactionRetryFailed {
871 #[snafu(implicit)]
872 location: Location,
873 },
874
875 #[cfg(any(feature = "pg_kvbackend", feature = "mysql_kvbackend"))]
876 #[snafu(display("Sql execution timeout, sql: {}, duration: {:?}", sql, duration))]
877 SqlExecutionTimeout {
878 sql: String,
879 duration: std::time::Duration,
880 #[snafu(implicit)]
881 location: Location,
882 },
883
884 #[snafu(display(
885 "Datanode table info not found, table id: {}, datanode id: {}",
886 table_id,
887 datanode_id
888 ))]
889 DatanodeTableInfoNotFound {
890 datanode_id: DatanodeId,
891 table_id: TableId,
892 #[snafu(implicit)]
893 location: Location,
894 },
895
896 #[snafu(display("Invalid topic name prefix: {}", prefix))]
897 InvalidTopicNamePrefix {
898 prefix: String,
899 #[snafu(implicit)]
900 location: Location,
901 },
902
903 #[snafu(display("No leader found for table_id: {}", table_id))]
904 NoLeader {
905 table_id: TableId,
906 #[snafu(implicit)]
907 location: Location,
908 },
909
910 #[snafu(display(
911 "Procedure poison key already exists with a different value, key: {}, value: {}",
912 key,
913 value
914 ))]
915 ProcedurePoisonConflict {
916 key: String,
917 value: String,
918 #[snafu(implicit)]
919 location: Location,
920 },
921
922 #[snafu(display("Failed to put poison, table metadata may be corrupted"))]
923 PutPoison {
924 #[snafu(implicit)]
925 location: Location,
926 #[snafu(source)]
927 source: common_procedure::error::Error,
928 },
929
930 #[snafu(display("Invalid file path: {}", file_path))]
931 InvalidFilePath {
932 #[snafu(implicit)]
933 location: Location,
934 file_path: String,
935 },
936
937 #[snafu(display("Failed to serialize flexbuffers"))]
938 SerializeFlexbuffers {
939 #[snafu(implicit)]
940 location: Location,
941 #[snafu(source)]
942 error: flexbuffers::SerializationError,
943 },
944
945 #[snafu(display("Failed to deserialize flexbuffers"))]
946 DeserializeFlexbuffers {
947 #[snafu(implicit)]
948 location: Location,
949 #[snafu(source)]
950 error: flexbuffers::DeserializationError,
951 },
952
953 #[snafu(display("Failed to read flexbuffers"))]
954 ReadFlexbuffers {
955 #[snafu(implicit)]
956 location: Location,
957 #[snafu(source)]
958 error: flexbuffers::ReaderError,
959 },
960
961 #[snafu(display("Invalid file name: {}", reason))]
962 InvalidFileName {
963 #[snafu(implicit)]
964 location: Location,
965 reason: String,
966 },
967
968 #[snafu(display("Invalid file extension: {}", reason))]
969 InvalidFileExtension {
970 #[snafu(implicit)]
971 location: Location,
972 reason: String,
973 },
974
975 #[snafu(display("Failed to write object, file path: {}", file_path))]
976 WriteObject {
977 #[snafu(implicit)]
978 location: Location,
979 file_path: String,
980 #[snafu(source)]
981 error: object_store::Error,
982 },
983
984 #[snafu(display("Failed to read object, file path: {}", file_path))]
985 ReadObject {
986 #[snafu(implicit)]
987 location: Location,
988 file_path: String,
989 #[snafu(source)]
990 error: object_store::Error,
991 },
992
993 #[snafu(display("Missing column ids"))]
994 MissingColumnIds {
995 #[snafu(implicit)]
996 location: Location,
997 },
998
999 #[snafu(display(
1000 "Missing column in column metadata: {}, table: {}, table_id: {}",
1001 column_name,
1002 table_name,
1003 table_id,
1004 ))]
1005 MissingColumnInColumnMetadata {
1006 column_name: String,
1007 #[snafu(implicit)]
1008 location: Location,
1009 table_name: String,
1010 table_id: TableId,
1011 },
1012
1013 #[snafu(display(
1014 "Mismatch column id: column_name: {}, column_id: {}, table: {}, table_id: {}",
1015 column_name,
1016 column_id,
1017 table_name,
1018 table_id,
1019 ))]
1020 MismatchColumnId {
1021 column_name: String,
1022 column_id: u32,
1023 #[snafu(implicit)]
1024 location: Location,
1025 table_name: String,
1026 table_id: TableId,
1027 },
1028
1029 #[snafu(display("Failed to convert column def, column: {}", column))]
1030 ConvertColumnDef {
1031 column: String,
1032 #[snafu(implicit)]
1033 location: Location,
1034 source: api::error::Error,
1035 },
1036
1037 #[snafu(display("Failed to convert time ranges"))]
1038 ConvertTimeRanges {
1039 #[snafu(implicit)]
1040 location: Location,
1041 source: api::error::Error,
1042 },
1043
1044 #[snafu(display(
1045 "Column metadata inconsistencies found in table: {}, table_id: {}",
1046 table_name,
1047 table_id
1048 ))]
1049 ColumnMetadataConflicts {
1050 table_name: String,
1051 table_id: TableId,
1052 },
1053
1054 #[snafu(display(
1055 "Column not found in column metadata, column_name: {}, column_id: {}",
1056 column_name,
1057 column_id
1058 ))]
1059 ColumnNotFound { column_name: String, column_id: u32 },
1060
1061 #[snafu(display(
1062 "Column id mismatch, column_name: {}, expected column_id: {}, actual column_id: {}",
1063 column_name,
1064 expected_column_id,
1065 actual_column_id
1066 ))]
1067 ColumnIdMismatch {
1068 column_name: String,
1069 expected_column_id: u32,
1070 actual_column_id: u32,
1071 },
1072
1073 #[snafu(display(
1074 "Timestamp column mismatch, expected column_name: {}, expected column_id: {}, actual column_name: {}, actual column_id: {}",
1075 expected_column_name,
1076 expected_column_id,
1077 actual_column_name,
1078 actual_column_id,
1079 ))]
1080 TimestampMismatch {
1081 expected_column_name: String,
1082 expected_column_id: u32,
1083 actual_column_name: String,
1084 actual_column_id: u32,
1085 },
1086
1087 #[cfg(feature = "enterprise")]
1088 #[snafu(display("Too large duration"))]
1089 TooLargeDuration {
1090 #[snafu(source)]
1091 error: prost_types::DurationError,
1092 #[snafu(implicit)]
1093 location: Location,
1094 },
1095
1096 #[cfg(feature = "enterprise")]
1097 #[snafu(display("Negative duration"))]
1098 NegativeDuration {
1099 #[snafu(source)]
1100 error: prost_types::DurationError,
1101 #[snafu(implicit)]
1102 location: Location,
1103 },
1104
1105 #[cfg(feature = "enterprise")]
1106 #[snafu(display("Missing interval field"))]
1107 MissingInterval {
1108 #[snafu(implicit)]
1109 location: Location,
1110 },
1111}
1112
1113pub type Result<T> = std::result::Result<T, Error>;
1114
1115impl ErrorExt for Error {
1116 fn status_code(&self) -> StatusCode {
1117 use Error::*;
1118 match self {
1119 IllegalServerState { .. }
1120 | EtcdTxnOpResponse { .. }
1121 | EtcdFailed { .. }
1122 | EtcdTxnFailed { .. }
1123 | ConnectEtcd { .. }
1124 | MoveValues { .. }
1125 | GetCache { .. }
1126 | GetLatestCacheRetryExceeded { .. }
1127 | SerializeToJson { .. }
1128 | DeserializeFromJson { .. }
1129 | ElectionNoLeader { .. }
1130 | ElectionLeaderLeaseExpired { .. }
1131 | ElectionLeaderLeaseChanged { .. } => StatusCode::Internal,
1132
1133 NoLeader { .. } => StatusCode::TableUnavailable,
1134 ValueNotExist { .. }
1135 | ProcedurePoisonConflict { .. }
1136 | ProcedureStateReceiverNotFound { .. }
1137 | MissingColumnIds { .. }
1138 | MissingColumnInColumnMetadata { .. }
1139 | MismatchColumnId { .. }
1140 | ColumnMetadataConflicts { .. }
1141 | ColumnNotFound { .. }
1142 | ColumnIdMismatch { .. }
1143 | TimestampMismatch { .. } => StatusCode::Unexpected,
1144
1145 Unsupported { .. } | ReadOnlyKvBackend { .. } => StatusCode::Unsupported,
1146 WriteObject { .. } | ReadObject { .. } => StatusCode::StorageUnavailable,
1147
1148 SerdeJson { .. }
1149 | ParseOption { .. }
1150 | RouteInfoCorrupted { .. }
1151 | InvalidProtoMsg { .. }
1152 | InvalidMetadata { .. }
1153 | Unexpected { .. }
1154 | TableInfoNotFound { .. }
1155 | NextSequence { .. }
1156 | UnexpectedSequenceValue { .. }
1157 | InvalidHeartbeatResponse { .. }
1158 | EncodeJson { .. }
1159 | DecodeJson { .. }
1160 | PayloadNotExist { .. }
1161 | ConvertRawKey { .. }
1162 | DecodeProto { .. }
1163 | BuildTableMeta { .. }
1164 | TableRouteNotFound { .. }
1165 | TableRepartNotFound { .. }
1166 | RegionOperatingRace { .. }
1167 | SerializeWalOptions { .. }
1168 | BuildKafkaClient { .. }
1169 | BuildKafkaCtrlClient { .. }
1170 | KafkaPartitionClient { .. }
1171 | ProduceRecord { .. }
1172 | CreateKafkaWalTopic { .. }
1173 | EmptyTopicPool { .. }
1174 | UnexpectedLogicalRouteTable { .. }
1175 | ProcedureOutput { .. }
1176 | FromUtf8 { .. }
1177 | MetadataCorruption { .. }
1178 | KafkaGetOffset { .. }
1179 | ReadFlexbuffers { .. }
1180 | SerializeFlexbuffers { .. }
1181 | DeserializeFlexbuffers { .. }
1182 | ConvertTimeRanges { .. } => StatusCode::Unexpected,
1183
1184 GetKvCache { .. } | CacheNotGet { .. } => StatusCode::Internal,
1185
1186 SchemaAlreadyExists { .. } => StatusCode::DatabaseAlreadyExists,
1187
1188 ProcedureNotFound { .. }
1189 | InvalidViewInfo { .. }
1190 | PrimaryKeyNotFound { .. }
1191 | EmptyKey { .. }
1192 | AlterLogicalTablesInvalidArguments { .. }
1193 | CreateLogicalTablesInvalidArguments { .. }
1194 | MismatchPrefix { .. }
1195 | TlsConfig { .. }
1196 | InvalidSetDatabaseOption { .. }
1197 | InvalidUnsetDatabaseOption { .. }
1198 | InvalidTopicNamePrefix { .. }
1199 | InvalidFileExtension { .. }
1200 | InvalidFileName { .. }
1201 | InvalidFlowRequestBody { .. }
1202 | InvalidFilePath { .. } => StatusCode::InvalidArguments,
1203
1204 #[cfg(feature = "enterprise")]
1205 MissingInterval { .. } | NegativeDuration { .. } | TooLargeDuration { .. } => {
1206 StatusCode::InvalidArguments
1207 }
1208
1209 FlowNotFound { .. } => StatusCode::FlowNotFound,
1210 FlowRouteNotFound { .. } => StatusCode::Unexpected,
1211 FlowAlreadyExists { .. } => StatusCode::FlowAlreadyExists,
1212
1213 ViewNotFound { .. } | TableNotFound { .. } | RegionNotFound { .. } => {
1214 StatusCode::TableNotFound
1215 }
1216 ViewAlreadyExists { .. } | TableAlreadyExists { .. } => StatusCode::TableAlreadyExists,
1217
1218 SubmitProcedure { source, .. }
1219 | QueryProcedure { source, .. }
1220 | WaitProcedure { source, .. }
1221 | StartProcedureManager { source, .. }
1222 | StopProcedureManager { source, .. } => source.status_code(),
1223 RegisterProcedureLoader { source, .. } => source.status_code(),
1224 External { source, .. } => source.status_code(),
1225 ResponseExceededSizeLimit { source, .. } => source.status_code(),
1226 OperateDatanode { source, .. } => source.status_code(),
1227 Table { source, .. } => source.status_code(),
1228 RetryLater { source, .. } => source.status_code(),
1229 AbortProcedure { source, .. } => source.status_code(),
1230 ConvertAlterTableRequest { source, .. } => source.status_code(),
1231 PutPoison { source, .. } => source.status_code(),
1232 ConvertColumnDef { source, .. } => source.status_code(),
1233 ProcedureStateReceiver { source, .. } => source.status_code(),
1234 RegisterRepartitionProcedureLoader { source, .. } => source.status_code(),
1235 CreateRepartitionProcedure { source, .. } => source.status_code(),
1236
1237 ParseProcedureId { .. }
1238 | InvalidNumTopics { .. }
1239 | SchemaNotFound { .. }
1240 | CatalogNotFound { .. }
1241 | InvalidNodeInfoKey { .. }
1242 | InvalidStatKey { .. }
1243 | ParseNum { .. }
1244 | InvalidRole { .. }
1245 | EmptyDdlTasks { .. } => StatusCode::InvalidArguments,
1246
1247 LoadTlsCertificate { .. } => StatusCode::Internal,
1248
1249 #[cfg(feature = "pg_kvbackend")]
1250 PostgresExecution { .. }
1251 | CreatePostgresPool { .. }
1252 | GetPostgresConnection { .. }
1253 | GetPostgresClient { .. }
1254 | PostgresTransaction { .. }
1255 | PostgresTlsConfig { .. }
1256 | InvalidTlsConfig { .. } => StatusCode::Internal,
1257 #[cfg(feature = "mysql_kvbackend")]
1258 MySqlExecution { .. }
1259 | CreateMySqlPool { .. }
1260 | DecodeSqlValue { .. }
1261 | AcquireMySqlClient { .. }
1262 | MySqlTransaction { .. } => StatusCode::Internal,
1263 #[cfg(any(feature = "pg_kvbackend", feature = "mysql_kvbackend"))]
1264 RdsTransactionRetryFailed { .. } | SqlExecutionTimeout { .. } => StatusCode::Internal,
1265 DatanodeTableInfoNotFound { .. } => StatusCode::Internal,
1266 }
1267 }
1268
1269 fn as_any(&self) -> &dyn std::any::Any {
1270 self
1271 }
1272
1273 fn retry_hint(&self) -> RetryHint {
1274 use Error::*;
1275
1276 match self {
1277 RetryLater { .. }
1278 | GetLatestCacheRetryExceeded { .. }
1279 | NoLeader { .. }
1280 | ElectionNoLeader { .. }
1281 | ElectionLeaderLeaseExpired { .. }
1282 | ElectionLeaderLeaseChanged { .. } => RetryHint::Retryable,
1283 WriteObject { error, .. } | ReadObject { error, .. } => {
1284 retry_hint_from_opendal_error(error)
1285 }
1286 BuildKafkaClient { error, .. }
1287 | BuildKafkaCtrlClient { error, .. }
1288 | KafkaPartitionClient { error, .. }
1289 | KafkaGetOffset { error, .. }
1290 | ProduceRecord { error, .. }
1291 | CreateKafkaWalTopic { error, .. } => rskafka_client_error_to_retry_hint(error),
1292 SubmitProcedure { source, .. }
1293 | QueryProcedure { source, .. }
1294 | WaitProcedure { source, .. }
1295 | StartProcedureManager { source, .. }
1296 | StopProcedureManager { source, .. }
1297 | RegisterProcedureLoader { source, .. }
1298 | PutPoison { source, .. }
1299 | ProcedureStateReceiver { source, .. } => source.retry_hint(),
1300 External { source, .. }
1301 | ResponseExceededSizeLimit { source, .. }
1302 | OperateDatanode { source, .. }
1303 | AbortProcedure { source, .. }
1304 | RegisterRepartitionProcedureLoader { source, .. }
1305 | CreateRepartitionProcedure { source, .. } => source.retry_hint(),
1306 Table { source, .. } => source.retry_hint(),
1307 ConvertAlterTableRequest { source, .. } => source.retry_hint(),
1308 ConvertColumnDef { source, .. } => source.retry_hint(),
1309 GetCache { source, .. } => source.retry_hint(),
1310 _ => RetryHint::NonRetryable,
1311 }
1312 }
1313}
1314
1315impl Error {
1316 #[cfg(any(feature = "pg_kvbackend", feature = "mysql_kvbackend"))]
1317 pub fn is_serialization_error(&self) -> bool {
1319 match self {
1320 #[cfg(feature = "pg_kvbackend")]
1321 Error::PostgresTransaction { error, .. } => {
1322 error.code() == Some(&tokio_postgres::error::SqlState::T_R_SERIALIZATION_FAILURE)
1323 }
1324 #[cfg(feature = "pg_kvbackend")]
1325 Error::PostgresExecution { error, .. } => {
1326 error.code() == Some(&tokio_postgres::error::SqlState::T_R_SERIALIZATION_FAILURE)
1327 }
1328 #[cfg(feature = "mysql_kvbackend")]
1329 Error::MySqlExecution {
1330 error: sqlx::Error::Database(database_error),
1331 ..
1332 } => {
1333 matches!(
1334 database_error.message(),
1335 "Deadlock found when trying to get lock; try restarting transaction"
1336 | "can't serialize access for this transaction"
1337 )
1338 }
1339 _ => false,
1340 }
1341 }
1342
1343 pub fn retry_later<E: ErrorExt + Send + Sync + 'static>(err: E) -> Error {
1345 Error::RetryLater {
1346 source: BoxedError::new(err),
1347 clean_poisons: false,
1348 }
1349 }
1350
1351 pub fn is_retry_later(&self) -> bool {
1353 matches!(
1354 self,
1355 Error::RetryLater { .. } | Error::GetLatestCacheRetryExceeded { .. }
1356 )
1357 }
1358
1359 pub fn need_clean_poisons(&self) -> bool {
1361 matches!(
1362 self,
1363 Error::AbortProcedure { clean_poisons, .. } if *clean_poisons
1364 ) || matches!(
1365 self,
1366 Error::RetryLater { clean_poisons, .. } if *clean_poisons
1367 )
1368 }
1369
1370 pub fn is_exceeded_size_limit(&self) -> bool {
1372 match self {
1373 Error::EtcdFailed {
1374 error: etcd_client::Error::GRpcStatus(status),
1375 ..
1376 } => status.code() == tonic::Code::OutOfRange,
1377 Error::ResponseExceededSizeLimit { .. } => true,
1378 _ => false,
1379 }
1380 }
1381}
1382
1383#[cfg(test)]
1384mod retry_hint_tests {
1385 use std::sync::Arc;
1386
1387 use common_error::mock::MockError;
1388
1389 use super::*;
1390
1391 #[test]
1392 fn test_retry_later_hint_is_retryable() {
1393 let err = Error::retry_later(MockError::new(StatusCode::Internal));
1394
1395 assert_eq!(err.retry_hint(), RetryHint::Retryable);
1396 }
1397
1398 #[test]
1399 fn test_latest_cache_retry_exceeded_hint_is_retryable() {
1400 let err = GetLatestCacheRetryExceededSnafu { attempts: 3_usize }.build();
1401
1402 assert_eq!(err.retry_hint(), RetryHint::Retryable);
1403 }
1404
1405 #[test]
1406 fn test_get_cache_forwards_retry_hint() {
1407 let source = Arc::new(Error::retry_later(MockError::new(StatusCode::Internal)));
1408 let err = Error::GetCache { source };
1409
1410 assert_eq!(err.retry_hint(), RetryHint::Retryable);
1411 }
1412
1413 #[test]
1414 fn test_default_hint_is_non_retryable() {
1415 let err = UnexpectedSnafu {
1416 err_msg: "mock error",
1417 }
1418 .build();
1419
1420 assert_eq!(err.retry_hint(), RetryHint::NonRetryable);
1421 }
1422}