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 #[snafu(source)]
205 source: servers::error::Error,
206 },
207
208 #[snafu(display("Failed to shutdown instance"))]
209 ShutdownInstance {
210 #[snafu(implicit)]
211 location: Location,
212 #[snafu(source)]
213 source: BoxedError,
214 },
215
216 #[snafu(display("Payload not exist"))]
217 PayloadNotExist {
218 #[snafu(implicit)]
219 location: Location,
220 },
221
222 #[snafu(display("Unexpected, violated: {}", violated))]
223 Unexpected {
224 violated: String,
225 #[snafu(implicit)]
226 location: Location,
227 },
228
229 #[snafu(display("Failed to handle request for region {}", region_id))]
230 HandleRegionRequest {
231 region_id: RegionId,
232 #[snafu(implicit)]
233 location: Location,
234 source: BoxedError,
235 },
236
237 #[snafu(display("Failed to open batch regions"))]
238 HandleBatchOpenRequest {
239 #[snafu(implicit)]
240 location: Location,
241 source: BoxedError,
242 },
243
244 #[snafu(display("Failed to handle batch ddl request, ddl_type: {}", ddl_type))]
245 HandleBatchDdlRequest {
246 #[snafu(implicit)]
247 location: Location,
248 source: BoxedError,
249 ddl_type: String,
250 },
251
252 #[snafu(display("RegionId {} not found", region_id))]
253 RegionNotFound {
254 region_id: RegionId,
255 #[snafu(implicit)]
256 location: Location,
257 },
258
259 #[snafu(display("Region {} not ready", region_id))]
260 RegionNotReady {
261 region_id: RegionId,
262 #[snafu(implicit)]
263 location: Location,
264 },
265
266 #[snafu(display("Region {} is busy", region_id))]
267 RegionBusy {
268 region_id: RegionId,
269 #[snafu(implicit)]
270 location: Location,
271 },
272
273 #[snafu(display("Region engine {} is not registered", name))]
274 RegionEngineNotFound {
275 name: String,
276 #[snafu(implicit)]
277 location: Location,
278 },
279
280 #[snafu(display("Unsupported output type, expected: {}", expected))]
281 UnsupportedOutput {
282 expected: String,
283 #[snafu(implicit)]
284 location: Location,
285 },
286
287 #[snafu(display("Failed to build region requests"))]
288 BuildRegionRequests {
289 #[snafu(implicit)]
290 location: Location,
291 source: store_api::metadata::MetadataError,
292 },
293
294 #[snafu(display("Failed to stop region engine {}", name))]
295 StopRegionEngine {
296 name: String,
297 #[snafu(implicit)]
298 location: Location,
299 source: BoxedError,
300 },
301
302 #[snafu(display(
303 "Failed to find logical regions in physical region {}",
304 physical_region_id
305 ))]
306 FindLogicalRegions {
307 physical_region_id: RegionId,
308 source: metric_engine::error::Error,
309 #[snafu(implicit)]
310 location: Location,
311 },
312
313 #[snafu(display("Failed to build mito engine"))]
314 BuildMitoEngine {
315 source: mito2::error::Error,
316 #[snafu(implicit)]
317 location: Location,
318 },
319
320 #[snafu(display("Failed to build metric engine"))]
321 BuildMetricEngine {
322 source: metric_engine::error::Error,
323 #[snafu(implicit)]
324 location: Location,
325 },
326
327 #[snafu(display("Failed to run gc for region {}", region_id))]
328 GcMitoEngine {
329 region_id: RegionId,
330 source: mito2::error::Error,
331 #[snafu(implicit)]
332 location: Location,
333 },
334
335 #[snafu(display("Failed to list SST entries from storage"))]
336 ListStorageSsts {
337 #[snafu(implicit)]
338 location: Location,
339 source: mito2::error::Error,
340 },
341
342 #[snafu(display("Failed to serialize options to TOML"))]
343 TomlFormat {
344 #[snafu(implicit)]
345 location: Location,
346 #[snafu(source(from(common_config::error::Error, Box::new)))]
347 source: Box<common_config::error::Error>,
348 },
349
350 #[snafu(display(
351 "Failed to get region metadata from engine {} for region_id {}",
352 engine,
353 region_id,
354 ))]
355 GetRegionMetadata {
356 engine: String,
357 region_id: RegionId,
358 #[snafu(implicit)]
359 location: Location,
360 source: BoxedError,
361 },
362
363 #[snafu(display("DataFusion"))]
364 DataFusion {
365 #[snafu(source)]
366 error: datafusion::error::DataFusionError,
367 #[snafu(implicit)]
368 location: Location,
369 },
370
371 #[snafu(display("Failed to acquire permit, source closed"))]
372 ConcurrentQueryLimiterClosed {
373 #[snafu(source)]
374 error: tokio::sync::AcquireError,
375 #[snafu(implicit)]
376 location: Location,
377 },
378
379 #[snafu(display("Failed to acquire permit under timeouts"))]
380 ConcurrentQueryLimiterTimeout {
381 #[snafu(source)]
382 error: Elapsed,
383 #[snafu(implicit)]
384 location: Location,
385 },
386
387 #[snafu(display("Cache not found in registry"))]
388 MissingCache {
389 #[snafu(implicit)]
390 location: Location,
391 },
392
393 #[snafu(display("Failed to serialize json"))]
394 SerializeJson {
395 #[snafu(source)]
396 error: serde_json::Error,
397 #[snafu(implicit)]
398 location: Location,
399 },
400
401 #[snafu(display("Failed object store operation"))]
402 ObjectStore {
403 source: object_store::error::Error,
404 #[snafu(implicit)]
405 location: Location,
406 },
407
408 #[snafu(display("Not yet implemented: {what}"))]
409 NotYetImplemented { what: String },
410}
411
412pub type Result<T> = std::result::Result<T, Error>;
413
414impl ErrorExt for Error {
415 fn status_code(&self) -> StatusCode {
416 use Error::*;
417 match self {
418 NewPlanDecoder { source, .. } | ExecuteLogicalPlan { source, .. } => {
419 source.status_code()
420 }
421
422 BuildRegionRequests { source, .. } => source.status_code(),
423 HandleHeartbeatResponse { source, .. } | GetMetadata { source, .. } => {
424 source.status_code()
425 }
426
427 DecodeLogicalPlan { source, .. } => source.status_code(),
428
429 Delete { source, .. } => source.status_code(),
430
431 InvalidSql { .. }
432 | IllegalPrimaryKeysDef { .. }
433 | MissingTimestampColumn { .. }
434 | SchemaNotFound { .. }
435 | SchemaExists { .. }
436 | MissingNodeId { .. }
437 | ColumnNoneDefaultValue { .. }
438 | MissingRequiredField { .. }
439 | RegionEngineNotFound { .. }
440 | ParseAddr { .. }
441 | TomlFormat { .. }
442 | BuildDatanode { .. } => StatusCode::InvalidArguments,
443
444 PayloadNotExist { .. }
445 | Unexpected { .. }
446 | WatchAsyncTaskChange { .. }
447 | BuildHttpClient { .. } => StatusCode::Unexpected,
448
449 AsyncTaskExecute { source, .. } => source.status_code(),
450
451 CreateDir { .. } | RemoveDir { .. } | ShutdownInstance { .. } | DataFusion { .. } => {
452 StatusCode::Internal
453 }
454
455 RegionNotFound { .. } => StatusCode::RegionNotFound,
456 RegionNotReady { .. } => StatusCode::RegionNotReady,
457 RegionBusy { .. } => StatusCode::RegionBusy,
458
459 StartServer { source, .. } | ShutdownServer { source, .. } => source.status_code(),
460
461 OpenLogStore { source, .. } => source.status_code(),
462 MetaClientInit { source, .. } => source.status_code(),
463 UnsupportedOutput { .. } | NotYetImplemented { .. } => StatusCode::Unsupported,
464 HandleRegionRequest { source, .. }
465 | GetRegionMetadata { source, .. }
466 | HandleBatchOpenRequest { source, .. }
467 | HandleBatchDdlRequest { source, .. } => source.status_code(),
468 StopRegionEngine { source, .. } => source.status_code(),
469
470 FindLogicalRegions { source, .. } => source.status_code(),
471 BuildMitoEngine { source, .. } | GcMitoEngine { source, .. } => source.status_code(),
472 BuildMetricEngine { source, .. } => source.status_code(),
473 ListStorageSsts { source, .. } => source.status_code(),
474 ConcurrentQueryLimiterClosed { .. } | ConcurrentQueryLimiterTimeout { .. } => {
475 StatusCode::RegionBusy
476 }
477 MissingCache { .. } => StatusCode::Internal,
478 SerializeJson { .. } => StatusCode::Internal,
479
480 ObjectStore { source, .. } => source.status_code(),
481 }
482 }
483
484 fn as_any(&self) -> &dyn Any {
485 self
486 }
487}
488
489define_into_tonic_status!(Error);