1use std::any::Any;
16use std::sync::Arc;
17
18use common_error::define_into_tonic_status;
19use common_error::ext::{BoxedError, ErrorExt};
20use common_error::status_code::StatusCode;
21use common_macro::stack_trace_debug;
22use snafu::{Location, Snafu};
23use store_api::storage::RegionId;
24use table::error::Error as TableError;
25use tokio::time::error::Elapsed;
26
27#[derive(Snafu)]
29#[snafu(visibility(pub))]
30#[stack_trace_debug]
31pub enum Error {
32    #[snafu(display("Failed to execute async task"))]
33    AsyncTaskExecute {
34        #[snafu(implicit)]
35        location: Location,
36        source: Arc<Error>,
37    },
38
39    #[snafu(display("Failed to watch change"))]
40    WatchAsyncTaskChange {
41        #[snafu(implicit)]
42        location: Location,
43        #[snafu(source)]
44        error: tokio::sync::watch::error::RecvError,
45    },
46
47    #[snafu(display("Failed to handle heartbeat response"))]
48    HandleHeartbeatResponse {
49        #[snafu(implicit)]
50        location: Location,
51        source: common_meta::error::Error,
52    },
53
54    #[snafu(display("Failed to get info from meta server"))]
55    GetMetadata {
56        #[snafu(implicit)]
57        location: Location,
58        source: common_meta::error::Error,
59    },
60
61    #[snafu(display("Failed to execute logical plan"))]
62    ExecuteLogicalPlan {
63        #[snafu(implicit)]
64        location: Location,
65        source: query::error::Error,
66    },
67
68    #[snafu(display("Failed to create plan decoder"))]
69    NewPlanDecoder {
70        #[snafu(implicit)]
71        location: Location,
72        source: query::error::Error,
73    },
74
75    #[snafu(display("Failed to decode logical plan"))]
76    DecodeLogicalPlan {
77        #[snafu(implicit)]
78        location: Location,
79        source: common_query::error::Error,
80    },
81
82    #[snafu(display("Schema not found: {}", name))]
83    SchemaNotFound {
84        name: String,
85        #[snafu(implicit)]
86        location: Location,
87    },
88
89    #[snafu(display("Missing timestamp column in request"))]
90    MissingTimestampColumn {
91        #[snafu(implicit)]
92        location: Location,
93    },
94
95    #[snafu(display("Failed to delete value from table: {}", table_name))]
96    Delete {
97        table_name: String,
98        #[snafu(implicit)]
99        location: Location,
100        source: TableError,
101    },
102
103    #[snafu(display("Failed to start server"))]
104    StartServer {
105        #[snafu(implicit)]
106        location: Location,
107        source: servers::error::Error,
108    },
109
110    #[snafu(display("Failed to parse address {}", addr))]
111    ParseAddr {
112        addr: String,
113        #[snafu(source)]
114        error: std::net::AddrParseError,
115    },
116
117    #[snafu(display("Failed to create directory {}", dir))]
118    CreateDir {
119        dir: String,
120        #[snafu(source)]
121        error: std::io::Error,
122    },
123
124    #[snafu(display("Failed to remove directory {}", dir))]
125    RemoveDir {
126        dir: String,
127        #[snafu(source)]
128        error: std::io::Error,
129    },
130
131    #[snafu(display("Failed to open log store"))]
132    OpenLogStore {
133        #[snafu(implicit)]
134        location: Location,
135        source: Box<log_store::error::Error>,
136    },
137
138    #[snafu(display("Invalid SQL, error: {}", msg))]
139    InvalidSql { msg: String },
140
141    #[snafu(display("Illegal primary keys definition: {}", msg))]
142    IllegalPrimaryKeysDef {
143        msg: String,
144        #[snafu(implicit)]
145        location: Location,
146    },
147
148    #[snafu(display("Schema {} already exists", name))]
149    SchemaExists {
150        name: String,
151        #[snafu(implicit)]
152        location: Location,
153    },
154
155    #[snafu(display("Failed to initialize meta client"))]
156    MetaClientInit {
157        #[snafu(implicit)]
158        location: Location,
159        source: meta_client::error::Error,
160    },
161
162    #[snafu(display("Missing node id in Datanode config"))]
163    MissingNodeId {
164        #[snafu(implicit)]
165        location: Location,
166    },
167
168    #[snafu(display("Failed to build datanode"))]
169    BuildDatanode {
170        #[snafu(implicit)]
171        location: Location,
172        source: BoxedError,
173    },
174
175    #[snafu(display("Failed to build http client"))]
176    BuildHttpClient {
177        #[snafu(implicit)]
178        location: Location,
179        #[snafu(source)]
180        error: reqwest::Error,
181    },
182
183    #[snafu(display("Missing required field: {}", name))]
184    MissingRequiredField {
185        name: String,
186        #[snafu(implicit)]
187        location: Location,
188    },
189
190    #[snafu(display(
191        "No valid default value can be built automatically, column: {}",
192        column,
193    ))]
194    ColumnNoneDefaultValue {
195        column: String,
196        #[snafu(implicit)]
197        location: Location,
198    },
199
200    #[snafu(display("Failed to shutdown server"))]
201    ShutdownServer {
202        #[snafu(implicit)]
203        location: Location,
204        source: servers::error::Error,
205    },
206
207    #[snafu(display("Failed to shutdown instance"))]
208    ShutdownInstance {
209        #[snafu(implicit)]
210        location: Location,
211        source: BoxedError,
212    },
213
214    #[snafu(display("Payload not exist"))]
215    PayloadNotExist {
216        #[snafu(implicit)]
217        location: Location,
218    },
219
220    #[snafu(display("Unexpected, violated: {}", violated))]
221    Unexpected {
222        violated: String,
223        #[snafu(implicit)]
224        location: Location,
225    },
226
227    #[snafu(display("Failed to handle request for region {}", region_id))]
228    HandleRegionRequest {
229        region_id: RegionId,
230        #[snafu(implicit)]
231        location: Location,
232        source: BoxedError,
233    },
234
235    #[snafu(display("Failed to open batch regions"))]
236    HandleBatchOpenRequest {
237        #[snafu(implicit)]
238        location: Location,
239        source: BoxedError,
240    },
241
242    #[snafu(display("Failed to handle batch ddl request, ddl_type: {}", ddl_type))]
243    HandleBatchDdlRequest {
244        #[snafu(implicit)]
245        location: Location,
246        source: BoxedError,
247        ddl_type: String,
248    },
249
250    #[snafu(display("RegionId {} not found", region_id))]
251    RegionNotFound {
252        region_id: RegionId,
253        #[snafu(implicit)]
254        location: Location,
255    },
256
257    #[snafu(display("Region {} not ready", region_id))]
258    RegionNotReady {
259        region_id: RegionId,
260        #[snafu(implicit)]
261        location: Location,
262    },
263
264    #[snafu(display("Region {} is busy", region_id))]
265    RegionBusy {
266        region_id: RegionId,
267        #[snafu(implicit)]
268        location: Location,
269    },
270
271    #[snafu(display("Region engine {} is not registered", name))]
272    RegionEngineNotFound {
273        name: String,
274        #[snafu(implicit)]
275        location: Location,
276    },
277
278    #[snafu(display("Unsupported output type, expected: {}", expected))]
279    UnsupportedOutput {
280        expected: String,
281        #[snafu(implicit)]
282        location: Location,
283    },
284
285    #[snafu(display("Failed to build region requests"))]
286    BuildRegionRequests {
287        #[snafu(implicit)]
288        location: Location,
289        source: store_api::metadata::MetadataError,
290    },
291
292    #[snafu(display("Failed to stop region engine {}", name))]
293    StopRegionEngine {
294        name: String,
295        #[snafu(implicit)]
296        location: Location,
297        source: BoxedError,
298    },
299
300    #[snafu(display(
301        "Failed to find logical regions in physical region {}",
302        physical_region_id
303    ))]
304    FindLogicalRegions {
305        physical_region_id: RegionId,
306        source: metric_engine::error::Error,
307        #[snafu(implicit)]
308        location: Location,
309    },
310
311    #[snafu(display("Failed to build mito engine"))]
312    BuildMitoEngine {
313        source: mito2::error::Error,
314        #[snafu(implicit)]
315        location: Location,
316    },
317
318    #[snafu(display("Failed to build metric engine"))]
319    BuildMetricEngine {
320        source: metric_engine::error::Error,
321        #[snafu(implicit)]
322        location: Location,
323    },
324
325    #[snafu(display("Failed to run gc for region {}", region_id))]
326    GcMitoEngine {
327        region_id: RegionId,
328        source: mito2::error::Error,
329        #[snafu(implicit)]
330        location: Location,
331    },
332
333    #[snafu(display("Invalid arguments for GC: {}", msg))]
334    InvalidGcArgs {
335        msg: String,
336        #[snafu(implicit)]
337        location: Location,
338    },
339
340    #[snafu(display("Failed to list SST entries from storage"))]
341    ListStorageSsts {
342        #[snafu(implicit)]
343        location: Location,
344        source: mito2::error::Error,
345    },
346
347    #[snafu(display("Failed to serialize options to TOML"))]
348    TomlFormat {
349        #[snafu(implicit)]
350        location: Location,
351        #[snafu(source(from(common_config::error::Error, Box::new)))]
352        source: Box<common_config::error::Error>,
353    },
354
355    #[snafu(display(
356        "Failed to get region metadata from engine {} for region_id {}",
357        engine,
358        region_id,
359    ))]
360    GetRegionMetadata {
361        engine: String,
362        region_id: RegionId,
363        #[snafu(implicit)]
364        location: Location,
365        source: BoxedError,
366    },
367
368    #[snafu(display("DataFusion"))]
369    DataFusion {
370        #[snafu(source)]
371        error: datafusion::error::DataFusionError,
372        #[snafu(implicit)]
373        location: Location,
374    },
375
376    #[snafu(display("Failed to acquire permit, source closed"))]
377    ConcurrentQueryLimiterClosed {
378        #[snafu(source)]
379        error: tokio::sync::AcquireError,
380        #[snafu(implicit)]
381        location: Location,
382    },
383
384    #[snafu(display("Failed to acquire permit under timeouts"))]
385    ConcurrentQueryLimiterTimeout {
386        #[snafu(source)]
387        error: Elapsed,
388        #[snafu(implicit)]
389        location: Location,
390    },
391
392    #[snafu(display("Cache not found in registry"))]
393    MissingCache {
394        #[snafu(implicit)]
395        location: Location,
396    },
397
398    #[snafu(display("Failed to serialize json"))]
399    SerializeJson {
400        #[snafu(source)]
401        error: serde_json::Error,
402        #[snafu(implicit)]
403        location: Location,
404    },
405
406    #[snafu(display("Failed object store operation"))]
407    ObjectStore {
408        source: object_store::error::Error,
409        #[snafu(implicit)]
410        location: Location,
411    },
412
413    #[snafu(display("Failed to build cache store"))]
414    BuildCacheStore {
415        #[snafu(source)]
416        error: object_store::Error,
417        #[snafu(implicit)]
418        location: Location,
419    },
420
421    #[snafu(display("Not yet implemented: {what}"))]
422    NotYetImplemented { what: String },
423}
424
425pub type Result<T> = std::result::Result<T, Error>;
426
427impl ErrorExt for Error {
428    fn status_code(&self) -> StatusCode {
429        use Error::*;
430        match self {
431            NewPlanDecoder { source, .. } | ExecuteLogicalPlan { source, .. } => {
432                source.status_code()
433            }
434
435            BuildRegionRequests { source, .. } => source.status_code(),
436            HandleHeartbeatResponse { source, .. } | GetMetadata { source, .. } => {
437                source.status_code()
438            }
439
440            DecodeLogicalPlan { source, .. } => source.status_code(),
441
442            Delete { source, .. } => source.status_code(),
443
444            InvalidSql { .. }
445            | IllegalPrimaryKeysDef { .. }
446            | MissingTimestampColumn { .. }
447            | SchemaNotFound { .. }
448            | SchemaExists { .. }
449            | MissingNodeId { .. }
450            | ColumnNoneDefaultValue { .. }
451            | MissingRequiredField { .. }
452            | RegionEngineNotFound { .. }
453            | ParseAddr { .. }
454            | TomlFormat { .. }
455            | BuildDatanode { .. } => StatusCode::InvalidArguments,
456
457            PayloadNotExist { .. }
458            | Unexpected { .. }
459            | WatchAsyncTaskChange { .. }
460            | BuildHttpClient { .. } => StatusCode::Unexpected,
461
462            AsyncTaskExecute { source, .. } => source.status_code(),
463
464            CreateDir { .. }
465            | RemoveDir { .. }
466            | ShutdownInstance { .. }
467            | DataFusion { .. }
468            | InvalidGcArgs { .. } => StatusCode::Internal,
469
470            RegionNotFound { .. } => StatusCode::RegionNotFound,
471            RegionNotReady { .. } => StatusCode::RegionNotReady,
472            RegionBusy { .. } => StatusCode::RegionBusy,
473
474            StartServer { source, .. } | ShutdownServer { source, .. } => source.status_code(),
475
476            OpenLogStore { source, .. } => source.status_code(),
477            MetaClientInit { source, .. } => source.status_code(),
478            UnsupportedOutput { .. } | NotYetImplemented { .. } => StatusCode::Unsupported,
479            HandleRegionRequest { source, .. }
480            | GetRegionMetadata { source, .. }
481            | HandleBatchOpenRequest { source, .. }
482            | HandleBatchDdlRequest { source, .. } => source.status_code(),
483            StopRegionEngine { source, .. } => source.status_code(),
484
485            FindLogicalRegions { source, .. } => source.status_code(),
486            BuildMitoEngine { source, .. } | GcMitoEngine { source, .. } => source.status_code(),
487            BuildMetricEngine { source, .. } => source.status_code(),
488            ListStorageSsts { source, .. } => source.status_code(),
489            ConcurrentQueryLimiterClosed { .. } | ConcurrentQueryLimiterTimeout { .. } => {
490                StatusCode::RegionBusy
491            }
492            MissingCache { .. } => StatusCode::Internal,
493            SerializeJson { .. } => StatusCode::Internal,
494
495            ObjectStore { source, .. } => source.status_code(),
496            BuildCacheStore { .. } => StatusCode::StorageUnavailable,
497        }
498    }
499
500    fn as_any(&self) -> &dyn Any {
501        self
502    }
503}
504
505define_into_tonic_status!(Error);