1use std::any::Any;
16
17use common_datasource::file_format::Format;
18use common_error::define_into_tonic_status;
19use common_error::ext::{BoxedError, ErrorExt, RetryHint};
20use common_error::status_code::StatusCode;
21use common_macro::stack_trace_debug;
22use common_query::error::datafusion_status_code;
23use datafusion::error::DataFusionError;
24use session::ReadPreference;
25use snafu::{Location, Snafu};
26use store_api::storage::RegionId;
27
28#[derive(Snafu)]
29#[snafu(visibility(pub))]
30#[stack_trace_debug]
31pub enum Error {
32 #[snafu(display("Failed to invalidate table cache"))]
33 InvalidateTableCache {
34 #[snafu(implicit)]
35 location: Location,
36 source: common_meta::error::Error,
37 },
38
39 #[snafu(display("Failed to handle heartbeat response"))]
40 HandleHeartbeatResponse {
41 #[snafu(implicit)]
42 location: Location,
43 source: common_meta::error::Error,
44 },
45
46 #[snafu(display("External error"))]
47 External {
48 #[snafu(implicit)]
49 location: Location,
50 source: BoxedError,
51 },
52
53 #[snafu(display("Failed to query"))]
54 RequestQuery {
55 #[snafu(implicit)]
56 location: Location,
57 source: common_meta::error::Error,
58 },
59
60 #[snafu(display("Failed to start server"))]
61 StartServer {
62 #[snafu(implicit)]
63 location: Location,
64 source: servers::error::Error,
65 },
66
67 #[snafu(display("Failed to shutdown server"))]
68 ShutdownServer {
69 #[snafu(implicit)]
70 location: Location,
71 source: servers::error::Error,
72 },
73
74 #[snafu(display("Failed to parse address {}", addr))]
75 ParseAddr {
76 addr: String,
77 #[snafu(source)]
78 error: std::net::AddrParseError,
79 },
80
81 #[snafu(display("Failed to parse SQL"))]
82 ParseSql {
83 #[snafu(implicit)]
84 location: Location,
85 source: sql::error::Error,
86 },
87
88 #[snafu(display("Invalid SQL, error: {}", err_msg))]
89 InvalidSql {
90 err_msg: String,
91 #[snafu(implicit)]
92 location: Location,
93 },
94
95 #[snafu(display("Incomplete GRPC request: {}", err_msg))]
96 IncompleteGrpcRequest {
97 err_msg: String,
98 #[snafu(implicit)]
99 location: Location,
100 },
101
102 #[snafu(display("Invalid InsertRequest, reason: {}", reason))]
103 InvalidInsertRequest {
104 reason: String,
105 #[snafu(implicit)]
106 location: Location,
107 },
108
109 #[snafu(display("Invalid DeleteRequest, reason: {}", reason))]
110 InvalidDeleteRequest {
111 reason: String,
112 #[snafu(implicit)]
113 location: Location,
114 },
115
116 #[snafu(display("Table not found: {}", table_name))]
117 TableNotFound { table_name: String },
118
119 #[snafu(display("General catalog error"))]
120 Catalog {
121 #[snafu(implicit)]
122 location: Location,
123 source: catalog::error::Error,
124 },
125
126 #[snafu(display("Failed to create heartbeat stream to Metasrv"))]
127 CreateMetaHeartbeatStream {
128 source: meta_client::error::Error,
129 #[snafu(implicit)]
130 location: Location,
131 },
132
133 #[snafu(display(
134 "Failed to find region peer for region id {}, read preference: {}",
135 region_id,
136 read_preference
137 ))]
138 FindRegionPeer {
139 region_id: RegionId,
140 read_preference: ReadPreference,
141 #[snafu(implicit)]
142 location: Location,
143 source: partition::error::Error,
144 },
145
146 #[snafu(display("Schema {} already exists", name))]
147 SchemaExists {
148 name: String,
149 #[snafu(implicit)]
150 location: Location,
151 },
152
153 #[snafu(display("Table occurs error"))]
154 Table {
155 #[snafu(implicit)]
156 location: Location,
157 source: table::error::Error,
158 },
159
160 #[snafu(display("Cannot find column by name: {}", msg))]
161 ColumnNotFound {
162 msg: String,
163 #[snafu(implicit)]
164 location: Location,
165 },
166
167 #[snafu(display(
168 "Ambiguous value column in table '{table_name}', candidates: {field_columns:?}"
169 ))]
170 AmbiguousValueColumn {
171 table_name: String,
172 field_columns: Vec<String>,
173 #[snafu(implicit)]
174 location: Location,
175 },
176
177 #[snafu(display("Unexpected type {data_type} for column '{column}' of table '{table_name}'"))]
178 UnexpectedColumnType {
179 table_name: String,
180 column: String,
181 data_type: String,
182 #[snafu(implicit)]
183 location: Location,
184 },
185
186 #[snafu(display("Failed to collect recordbatch"))]
187 CollectRecordbatch {
188 #[snafu(implicit)]
189 location: Location,
190 source: common_recordbatch::error::Error,
191 },
192
193 #[snafu(display("Failed to plan statement"))]
194 PlanStatement {
195 #[snafu(implicit)]
196 location: Location,
197 source: query::error::Error,
198 },
199
200 #[snafu(display("Failed to read table: {table_name}"))]
201 ReadTable {
202 table_name: String,
203 #[snafu(implicit)]
204 location: Location,
205 source: query::error::Error,
206 },
207
208 #[snafu(display("Failed to execute logical plan"))]
209 ExecLogicalPlan {
210 #[snafu(implicit)]
211 location: Location,
212 source: query::error::Error,
213 },
214
215 #[snafu(display("Not supported: {}", feat))]
216 NotSupported { feat: String },
217
218 #[snafu(display("SQL execution intercepted"))]
219 SqlExecIntercepted {
220 #[snafu(implicit)]
221 location: Location,
222 source: BoxedError,
223 },
224
225 #[snafu(display("Failed to execute PromQL query {}", query))]
227 ExecutePromql {
228 query: String,
229 #[snafu(implicit)]
230 location: Location,
231 source: servers::error::Error,
232 },
233
234 #[snafu(display("Invalid Prometheus remote read schema: {detail}"))]
235 InvalidPromRemoteReadSchema {
236 detail: String,
237 #[snafu(implicit)]
238 location: Location,
239 },
240
241 #[snafu(display("Failed to create logical plan for prometheus query"))]
242 PromStoreRemoteQueryPlan {
243 #[snafu(implicit)]
244 location: Location,
245 source: servers::error::Error,
246 },
247
248 #[snafu(display("Failed to create logical plan for prometheus metric names query"))]
249 PrometheusMetricNamesQueryPlan {
250 #[snafu(implicit)]
251 location: Location,
252 source: servers::error::Error,
253 },
254
255 #[snafu(display("Failed to create logical plan for prometheus label values query"))]
256 PrometheusLabelValuesQueryPlan {
257 #[snafu(implicit)]
258 location: Location,
259 source: query::promql::error::Error,
260 },
261
262 #[snafu(display("Failed to describe schema for given statement"))]
263 DescribeStatement {
264 #[snafu(implicit)]
265 location: Location,
266 source: query::error::Error,
267 },
268
269 #[snafu(display("Illegal primary keys definition: {}", msg))]
270 IllegalPrimaryKeysDef {
271 msg: String,
272 #[snafu(implicit)]
273 location: Location,
274 },
275
276 #[snafu(display("Failed to insert value into table: {}", table_name))]
277 Insert {
278 table_name: String,
279 #[snafu(implicit)]
280 location: Location,
281 source: table::error::Error,
282 },
283
284 #[snafu(display("Unsupported format: {:?}", format))]
285 UnsupportedFormat {
286 #[snafu(implicit)]
287 location: Location,
288 format: Format,
289 },
290
291 #[snafu(display("Failed to pass permission check"))]
292 Permission {
293 source: auth::error::Error,
294 #[snafu(implicit)]
295 location: Location,
296 },
297
298 #[snafu(display(
299 "No valid default value can be built automatically, column: {}",
300 column,
301 ))]
302 ColumnNoneDefaultValue {
303 column: String,
304 #[snafu(implicit)]
305 location: Location,
306 },
307
308 #[snafu(display("Table operation error"))]
309 TableOperation {
310 source: operator::error::Error,
311 #[snafu(implicit)]
312 location: Location,
313 },
314
315 #[snafu(display("Invalid auth config"))]
316 IllegalAuthConfig { source: auth::error::Error },
317
318 #[snafu(display("Failed to serialize options to TOML"))]
319 TomlFormat {
320 #[snafu(implicit)]
321 location: Location,
322 #[snafu(source(from(common_config::error::Error, Box::new)))]
323 source: Box<common_config::error::Error>,
324 },
325
326 #[snafu(display("Failed to get cache from cache registry: {}", name))]
327 CacheRequired {
328 #[snafu(implicit)]
329 location: Location,
330 name: String,
331 },
332
333 #[snafu(display("Invalid write retry config: {}", reason))]
334 InvalidWriteRetryConfig {
335 reason: &'static str,
336 #[snafu(implicit)]
337 location: Location,
338 },
339
340 #[snafu(display("Invalid tls config"))]
341 InvalidTlsConfig {
342 #[snafu(source)]
343 error: common_grpc::error::Error,
344 #[snafu(implicit)]
345 location: Location,
346 },
347
348 #[snafu(display("Failed to init plugin"))]
349 InitPlugin {
351 #[snafu(implicit)]
352 location: Location,
353 source: BoxedError,
354 },
355
356 #[snafu(display("Failed to decode logical plan from substrait"))]
357 SubstraitDecodeLogicalPlan {
358 #[snafu(implicit)]
359 location: Location,
360 source: common_query::error::Error,
361 },
362
363 #[snafu(display("DataFusionError"))]
364 DataFusion {
365 #[snafu(source)]
366 error: DataFusionError,
367 #[snafu(implicit)]
368 location: Location,
369 },
370
371 #[snafu(display("Query has been cancelled"))]
372 Cancelled {
373 #[snafu(implicit)]
374 location: Location,
375 },
376
377 #[snafu(display("Canceling statement due to statement timeout"))]
378 StatementTimeout {
379 #[snafu(implicit)]
380 location: Location,
381 },
382
383 #[snafu(display("Service suspended"))]
384 Suspended {
385 #[snafu(implicit)]
386 location: Location,
387 },
388}
389
390pub type Result<T> = std::result::Result<T, Error>;
391
392impl ErrorExt for Error {
393 fn status_code(&self) -> StatusCode {
394 match self {
395 Error::TomlFormat { .. }
396 | Error::ParseAddr { .. }
397 | Error::InvalidSql { .. }
398 | Error::InvalidInsertRequest { .. }
399 | Error::InvalidDeleteRequest { .. }
400 | Error::IllegalPrimaryKeysDef { .. }
401 | Error::SchemaExists { .. }
402 | Error::ColumnNotFound { .. }
403 | Error::AmbiguousValueColumn { .. }
404 | Error::InvalidPromRemoteReadSchema { .. }
405 | Error::UnsupportedFormat { .. }
406 | Error::IllegalAuthConfig { .. }
407 | Error::ColumnNoneDefaultValue { .. }
408 | Error::IncompleteGrpcRequest { .. }
409 | Error::InvalidTlsConfig { .. }
410 | Error::InvalidWriteRetryConfig { .. } => StatusCode::InvalidArguments,
411
412 Error::NotSupported { .. } => StatusCode::Unsupported,
413
414 Error::Permission { source, .. } => source.status_code(),
415
416 Error::DescribeStatement { source, .. } => source.status_code(),
417
418 Error::HandleHeartbeatResponse { source, .. } => source.status_code(),
419
420 Error::PromStoreRemoteQueryPlan { source, .. }
421 | Error::PrometheusMetricNamesQueryPlan { source, .. }
422 | Error::ExecutePromql { source, .. } => source.status_code(),
423
424 Error::SubstraitDecodeLogicalPlan { source, .. } => source.status_code(),
425
426 Error::PrometheusLabelValuesQueryPlan { source, .. } => source.status_code(),
427
428 Error::CollectRecordbatch { source, .. } => source.status_code(),
429
430 Error::SqlExecIntercepted { source, .. } => source.status_code(),
431 Error::StartServer { source, .. } => source.status_code(),
432 Error::ShutdownServer { source, .. } => source.status_code(),
433
434 Error::ParseSql { source, .. } => source.status_code(),
435
436 Error::InvalidateTableCache { source, .. } => source.status_code(),
437
438 Error::Table { source, .. } | Error::Insert { source, .. } => source.status_code(),
439
440 Error::RequestQuery { source, .. } => source.status_code(),
441
442 Error::CacheRequired { .. } | Error::UnexpectedColumnType { .. } => {
443 StatusCode::Internal
444 }
445
446 Error::TableNotFound { .. } => StatusCode::TableNotFound,
447
448 Error::Catalog { source, .. } => source.status_code(),
449
450 Error::CreateMetaHeartbeatStream { source, .. } => source.status_code(),
451
452 Error::PlanStatement { source, .. }
453 | Error::ReadTable { source, .. }
454 | Error::ExecLogicalPlan { source, .. } => source.status_code(),
455
456 Error::External { source, .. } | Error::InitPlugin { source, .. } => {
457 source.status_code()
458 }
459 Error::FindRegionPeer { source, .. } => source.status_code(),
460
461 Error::TableOperation { source, .. } => source.status_code(),
462
463 Error::DataFusion { error, .. } => datafusion_status_code::<Self>(error, None),
464
465 Error::Cancelled { .. } => StatusCode::Cancelled,
466
467 Error::StatementTimeout { .. } => StatusCode::Cancelled,
468
469 Error::Suspended { .. } => StatusCode::Suspended,
470 }
471 }
472
473 fn as_any(&self) -> &dyn Any {
474 self
475 }
476
477 fn retry_hint(&self) -> RetryHint {
478 match self {
479 Error::InvalidateTableCache { source, .. }
480 | Error::HandleHeartbeatResponse { source, .. }
481 | Error::RequestQuery { source, .. } => source.retry_hint(),
482
483 Error::External { source, .. }
484 | Error::SqlExecIntercepted { source, .. }
485 | Error::InitPlugin { source, .. } => source.retry_hint(),
486
487 Error::StartServer { source, .. }
488 | Error::ShutdownServer { source, .. }
489 | Error::ExecutePromql { source, .. }
490 | Error::PromStoreRemoteQueryPlan { source, .. }
491 | Error::PrometheusMetricNamesQueryPlan { source, .. } => source.retry_hint(),
492
493 Error::ParseSql { source, .. } => source.retry_hint(),
494 Error::Catalog { source, .. } => source.retry_hint(),
495 Error::CreateMetaHeartbeatStream { source, .. } => source.retry_hint(),
496 Error::FindRegionPeer { source, .. } => source.retry_hint(),
497 Error::Table { source, .. } => source.retry_hint(),
498 Error::CollectRecordbatch { source, .. } => source.retry_hint(),
499 Error::PlanStatement { source, .. }
500 | Error::ReadTable { source, .. }
501 | Error::ExecLogicalPlan { source, .. }
502 | Error::DescribeStatement { source, .. } => source.retry_hint(),
503 Error::PrometheusLabelValuesQueryPlan { source, .. } => source.retry_hint(),
504 Error::Insert { source, .. } => source.retry_hint(),
505 Error::Permission { source, .. } => source.retry_hint(),
506 Error::TableOperation { source, .. } => source.retry_hint(),
507 Error::IllegalAuthConfig { source, .. } => source.retry_hint(),
508 Error::TomlFormat { source, .. } => source.retry_hint(),
509 Error::InvalidTlsConfig { error, .. } => error.retry_hint(),
510 Error::SubstraitDecodeLogicalPlan { source, .. } => source.retry_hint(),
511
512 _ => RetryHint::NonRetryable,
513 }
514 }
515}
516
517define_into_tonic_status!(Error);
518
519impl From<operator::error::Error> for Error {
520 fn from(e: operator::error::Error) -> Error {
521 Error::TableOperation {
522 source: e,
523 location: Location::default(),
524 }
525 }
526}