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("Failed to create logical plan for prometheus query"))]
235 PromStoreRemoteQueryPlan {
236 #[snafu(implicit)]
237 location: Location,
238 source: servers::error::Error,
239 },
240
241 #[snafu(display("Failed to create logical plan for prometheus metric names query"))]
242 PrometheusMetricNamesQueryPlan {
243 #[snafu(implicit)]
244 location: Location,
245 source: servers::error::Error,
246 },
247
248 #[snafu(display("Failed to create logical plan for prometheus label values query"))]
249 PrometheusLabelValuesQueryPlan {
250 #[snafu(implicit)]
251 location: Location,
252 source: query::promql::error::Error,
253 },
254
255 #[snafu(display("Failed to describe schema for given statement"))]
256 DescribeStatement {
257 #[snafu(implicit)]
258 location: Location,
259 source: query::error::Error,
260 },
261
262 #[snafu(display("Illegal primary keys definition: {}", msg))]
263 IllegalPrimaryKeysDef {
264 msg: String,
265 #[snafu(implicit)]
266 location: Location,
267 },
268
269 #[snafu(display("Failed to insert value into table: {}", table_name))]
270 Insert {
271 table_name: String,
272 #[snafu(implicit)]
273 location: Location,
274 source: table::error::Error,
275 },
276
277 #[snafu(display("Unsupported format: {:?}", format))]
278 UnsupportedFormat {
279 #[snafu(implicit)]
280 location: Location,
281 format: Format,
282 },
283
284 #[snafu(display("Failed to pass permission check"))]
285 Permission {
286 source: auth::error::Error,
287 #[snafu(implicit)]
288 location: Location,
289 },
290
291 #[snafu(display(
292 "No valid default value can be built automatically, column: {}",
293 column,
294 ))]
295 ColumnNoneDefaultValue {
296 column: String,
297 #[snafu(implicit)]
298 location: Location,
299 },
300
301 #[snafu(display("Table operation error"))]
302 TableOperation {
303 source: operator::error::Error,
304 #[snafu(implicit)]
305 location: Location,
306 },
307
308 #[snafu(display("Invalid auth config"))]
309 IllegalAuthConfig { source: auth::error::Error },
310
311 #[snafu(display("Failed to serialize options to TOML"))]
312 TomlFormat {
313 #[snafu(implicit)]
314 location: Location,
315 #[snafu(source(from(common_config::error::Error, Box::new)))]
316 source: Box<common_config::error::Error>,
317 },
318
319 #[snafu(display("Failed to get cache from cache registry: {}", name))]
320 CacheRequired {
321 #[snafu(implicit)]
322 location: Location,
323 name: String,
324 },
325
326 #[snafu(display("Invalid tls config"))]
327 InvalidTlsConfig {
328 #[snafu(source)]
329 error: common_grpc::error::Error,
330 #[snafu(implicit)]
331 location: Location,
332 },
333
334 #[snafu(display("Failed to init plugin"))]
335 InitPlugin {
337 #[snafu(implicit)]
338 location: Location,
339 source: BoxedError,
340 },
341
342 #[snafu(display("Failed to decode logical plan from substrait"))]
343 SubstraitDecodeLogicalPlan {
344 #[snafu(implicit)]
345 location: Location,
346 source: common_query::error::Error,
347 },
348
349 #[snafu(display("DataFusionError"))]
350 DataFusion {
351 #[snafu(source)]
352 error: DataFusionError,
353 #[snafu(implicit)]
354 location: Location,
355 },
356
357 #[snafu(display("Query has been cancelled"))]
358 Cancelled {
359 #[snafu(implicit)]
360 location: Location,
361 },
362
363 #[snafu(display("Canceling statement due to statement timeout"))]
364 StatementTimeout {
365 #[snafu(implicit)]
366 location: Location,
367 },
368
369 #[snafu(display("Service suspended"))]
370 Suspended {
371 #[snafu(implicit)]
372 location: Location,
373 },
374}
375
376pub type Result<T> = std::result::Result<T, Error>;
377
378impl ErrorExt for Error {
379 fn status_code(&self) -> StatusCode {
380 match self {
381 Error::TomlFormat { .. }
382 | Error::ParseAddr { .. }
383 | Error::InvalidSql { .. }
384 | Error::InvalidInsertRequest { .. }
385 | Error::InvalidDeleteRequest { .. }
386 | Error::IllegalPrimaryKeysDef { .. }
387 | Error::SchemaExists { .. }
388 | Error::ColumnNotFound { .. }
389 | Error::AmbiguousValueColumn { .. }
390 | Error::UnsupportedFormat { .. }
391 | Error::IllegalAuthConfig { .. }
392 | Error::ColumnNoneDefaultValue { .. }
393 | Error::IncompleteGrpcRequest { .. }
394 | Error::InvalidTlsConfig { .. } => StatusCode::InvalidArguments,
395
396 Error::NotSupported { .. } => StatusCode::Unsupported,
397
398 Error::Permission { source, .. } => source.status_code(),
399
400 Error::DescribeStatement { source, .. } => source.status_code(),
401
402 Error::HandleHeartbeatResponse { source, .. } => source.status_code(),
403
404 Error::PromStoreRemoteQueryPlan { source, .. }
405 | Error::PrometheusMetricNamesQueryPlan { source, .. }
406 | Error::ExecutePromql { source, .. } => source.status_code(),
407
408 Error::SubstraitDecodeLogicalPlan { source, .. } => source.status_code(),
409
410 Error::PrometheusLabelValuesQueryPlan { source, .. } => source.status_code(),
411
412 Error::CollectRecordbatch { source, .. } => source.status_code(),
413
414 Error::SqlExecIntercepted { source, .. } => source.status_code(),
415 Error::StartServer { source, .. } => source.status_code(),
416 Error::ShutdownServer { source, .. } => source.status_code(),
417
418 Error::ParseSql { source, .. } => source.status_code(),
419
420 Error::InvalidateTableCache { source, .. } => source.status_code(),
421
422 Error::Table { source, .. } | Error::Insert { source, .. } => source.status_code(),
423
424 Error::RequestQuery { source, .. } => source.status_code(),
425
426 Error::CacheRequired { .. } | Error::UnexpectedColumnType { .. } => {
427 StatusCode::Internal
428 }
429
430 Error::TableNotFound { .. } => StatusCode::TableNotFound,
431
432 Error::Catalog { source, .. } => source.status_code(),
433
434 Error::CreateMetaHeartbeatStream { source, .. } => source.status_code(),
435
436 Error::PlanStatement { source, .. }
437 | Error::ReadTable { source, .. }
438 | Error::ExecLogicalPlan { source, .. } => source.status_code(),
439
440 Error::External { source, .. } | Error::InitPlugin { source, .. } => {
441 source.status_code()
442 }
443 Error::FindRegionPeer { source, .. } => source.status_code(),
444
445 Error::TableOperation { source, .. } => source.status_code(),
446
447 Error::DataFusion { error, .. } => datafusion_status_code::<Self>(error, None),
448
449 Error::Cancelled { .. } => StatusCode::Cancelled,
450
451 Error::StatementTimeout { .. } => StatusCode::Cancelled,
452
453 Error::Suspended { .. } => StatusCode::Suspended,
454 }
455 }
456
457 fn as_any(&self) -> &dyn Any {
458 self
459 }
460
461 fn retry_hint(&self) -> RetryHint {
462 match self {
463 Error::InvalidateTableCache { source, .. }
464 | Error::HandleHeartbeatResponse { source, .. }
465 | Error::RequestQuery { source, .. } => source.retry_hint(),
466
467 Error::External { source, .. }
468 | Error::SqlExecIntercepted { source, .. }
469 | Error::InitPlugin { source, .. } => source.retry_hint(),
470
471 Error::StartServer { source, .. }
472 | Error::ShutdownServer { source, .. }
473 | Error::ExecutePromql { source, .. }
474 | Error::PromStoreRemoteQueryPlan { source, .. }
475 | Error::PrometheusMetricNamesQueryPlan { source, .. } => source.retry_hint(),
476
477 Error::ParseSql { source, .. } => source.retry_hint(),
478 Error::Catalog { source, .. } => source.retry_hint(),
479 Error::CreateMetaHeartbeatStream { source, .. } => source.retry_hint(),
480 Error::FindRegionPeer { source, .. } => source.retry_hint(),
481 Error::Table { source, .. } => source.retry_hint(),
482 Error::CollectRecordbatch { source, .. } => source.retry_hint(),
483 Error::PlanStatement { source, .. }
484 | Error::ReadTable { source, .. }
485 | Error::ExecLogicalPlan { source, .. }
486 | Error::DescribeStatement { source, .. } => source.retry_hint(),
487 Error::PrometheusLabelValuesQueryPlan { source, .. } => source.retry_hint(),
488 Error::Insert { source, .. } => source.retry_hint(),
489 Error::Permission { source, .. } => source.retry_hint(),
490 Error::TableOperation { source, .. } => source.retry_hint(),
491 Error::IllegalAuthConfig { source, .. } => source.retry_hint(),
492 Error::TomlFormat { source, .. } => source.retry_hint(),
493 Error::InvalidTlsConfig { error, .. } => error.retry_hint(),
494 Error::SubstraitDecodeLogicalPlan { source, .. } => source.retry_hint(),
495
496 _ => RetryHint::NonRetryable,
497 }
498 }
499}
500
501define_into_tonic_status!(Error);
502
503impl From<operator::error::Error> for Error {
504 fn from(e: operator::error::Error) -> Error {
505 Error::TableOperation {
506 source: e,
507 location: Location::default(),
508 }
509 }
510}