Skip to main content

common_meta/
error.rs

1// Copyright 2023 Greptime Team
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::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    /// Check if the error is a serialization error.
1318    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    /// Creates a new [Error::RetryLater] error from source `err`.
1344    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    /// Determine whether it is a retry later type through [StatusCode]
1352    pub fn is_retry_later(&self) -> bool {
1353        matches!(
1354            self,
1355            Error::RetryLater { .. } | Error::GetLatestCacheRetryExceeded { .. }
1356        )
1357    }
1358
1359    /// Determine whether it needs to clean poisons.
1360    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    /// Returns true if the response exceeds the size limit.
1371    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}