1use std::any::Any;
16use std::net::SocketAddr;
17use std::string::FromUtf8Error;
18
19use axum::http::StatusCode as HttpStatusCode;
20use axum::response::{IntoResponse, Response};
21use axum::{Json, http};
22use base64::DecodeError;
23use common_base::readable_size::ReadableSize;
24use common_error::define_into_tonic_status;
25use common_error::ext::{BoxedError, ErrorExt};
26use common_error::status_code::StatusCode;
27use common_macro::stack_trace_debug;
28use common_telemetry::{error, warn};
29use datafusion::error::DataFusionError;
30use datatypes::prelude::ConcreteDataType;
31use headers::ContentType;
32use http::header::InvalidHeaderValue;
33use query::parser::PromQuery;
34use serde_json::json;
35use snafu::{Location, Snafu};
36
37#[derive(Snafu)]
38#[snafu(visibility(pub))]
39#[stack_trace_debug]
40pub enum Error {
41 #[snafu(display("Failed to bind address: {}", addr))]
42 AddressBind {
43 addr: SocketAddr,
44 #[snafu(source)]
45 error: std::io::Error,
46 #[snafu(implicit)]
47 location: Location,
48 },
49
50 #[snafu(display("Arrow error"))]
51 Arrow {
52 #[snafu(source)]
53 error: arrow_schema::ArrowError,
54 },
55
56 #[snafu(display("Internal error: {}", err_msg))]
57 Internal { err_msg: String },
58
59 #[snafu(display("Unsupported data type: {}, reason: {}", data_type, reason))]
60 UnsupportedDataType {
61 data_type: ConcreteDataType,
62 reason: String,
63 },
64
65 #[snafu(display("Internal IO error"))]
66 InternalIo {
67 #[snafu(source)]
68 error: std::io::Error,
69 },
70
71 #[snafu(display("Tokio IO error: {}", err_msg))]
72 TokioIo {
73 err_msg: String,
74 #[snafu(source)]
75 error: std::io::Error,
76 },
77
78 #[snafu(display("Failed to collect recordbatch"))]
79 CollectRecordbatch {
80 #[snafu(implicit)]
81 location: Location,
82 source: common_recordbatch::error::Error,
83 },
84
85 #[snafu(display("Failed to start HTTP server"))]
86 StartHttp {
87 #[snafu(source)]
88 error: hyper::Error,
89 },
90
91 #[snafu(display("Failed to start gRPC server"))]
92 StartGrpc {
93 #[snafu(source)]
94 error: tonic::transport::Error,
95 },
96
97 #[snafu(display("Request memory limit exceeded"))]
98 MemoryLimitExceeded {
99 #[snafu(implicit)]
100 location: Location,
101 source: common_memory_manager::Error,
102 },
103
104 #[snafu(display("{} server is already started", server))]
105 AlreadyStarted {
106 server: String,
107 #[snafu(implicit)]
108 location: Location,
109 },
110
111 #[snafu(display("Failed to bind address {}", addr))]
112 TcpBind {
113 addr: SocketAddr,
114 #[snafu(source)]
115 error: std::io::Error,
116 },
117
118 #[snafu(display("Failed to execute query"))]
119 ExecuteQuery {
120 #[snafu(implicit)]
121 location: Location,
122 source: BoxedError,
123 },
124
125 #[snafu(display("Failed to execute plan"))]
126 ExecutePlan {
127 #[snafu(implicit)]
128 location: Location,
129 source: BoxedError,
130 },
131
132 #[snafu(display("Execute gRPC query error"))]
133 ExecuteGrpcQuery {
134 #[snafu(implicit)]
135 location: Location,
136 source: BoxedError,
137 },
138
139 #[snafu(display("Execute gRPC request error"))]
140 ExecuteGrpcRequest {
141 #[snafu(implicit)]
142 location: Location,
143 source: BoxedError,
144 },
145
146 #[snafu(display("Failed to check database validity"))]
147 CheckDatabaseValidity {
148 #[snafu(implicit)]
149 location: Location,
150 source: BoxedError,
151 },
152
153 #[snafu(display("Failed to describe statement"))]
154 DescribeStatement { source: BoxedError },
155
156 #[snafu(display("Pipeline error"))]
157 Pipeline {
158 #[snafu(source)]
159 source: pipeline::error::Error,
160 #[snafu(implicit)]
161 location: Location,
162 },
163
164 #[snafu(display("Not supported: {}", feat))]
165 NotSupported { feat: String },
166
167 #[snafu(display("Invalid request parameter: {}", reason))]
168 InvalidParameter {
169 reason: String,
170 #[snafu(implicit)]
171 location: Location,
172 },
173
174 #[snafu(display(
175 "Too many concurrent large requests, limit: {}, request size: {}",
176 ReadableSize(*limit as u64),
177 ReadableSize(*request_size as u64)
178 ))]
179 TooManyConcurrentRequests {
180 limit: usize,
181 request_size: usize,
182 #[snafu(implicit)]
183 location: Location,
184 },
185
186 #[snafu(display("Invalid query: {}", reason))]
187 InvalidQuery {
188 reason: String,
189 #[snafu(implicit)]
190 location: Location,
191 },
192
193 #[snafu(display("Failed to parse query"))]
194 FailedToParseQuery {
195 #[snafu(implicit)]
196 location: Location,
197 source: sql::error::Error,
198 },
199
200 #[snafu(display("Failed to parse InfluxDB line protocol"))]
201 InfluxdbLineProtocol {
202 #[snafu(implicit)]
203 location: Location,
204 #[snafu(source)]
205 error: influxdb_line_protocol::Error,
206 },
207
208 #[snafu(display("Failed to write row"))]
209 RowWriter {
210 #[snafu(implicit)]
211 location: Location,
212 source: common_grpc::error::Error,
213 },
214
215 #[snafu(display("Failed to convert time precision, name: {}", name))]
216 TimePrecision {
217 name: String,
218 #[snafu(implicit)]
219 location: Location,
220 },
221
222 #[snafu(display("Invalid OpenTSDB Json request"))]
223 InvalidOpentsdbJsonRequest {
224 #[snafu(source)]
225 error: serde_json::error::Error,
226 #[snafu(implicit)]
227 location: Location,
228 },
229
230 #[snafu(display("Failed to decode prometheus remote request"))]
231 DecodePromRemoteRequest {
232 #[snafu(implicit)]
233 location: Location,
234 #[snafu(source)]
235 error: prost::DecodeError,
236 },
237
238 #[snafu(display(
239 "Failed to decode OTLP request (content-type: {content_type}): {error}. The endpoint only accepts 'application/x-protobuf' format."
240 ))]
241 DecodeOtlpRequest {
242 content_type: String,
243 #[snafu(implicit)]
244 location: Location,
245 #[snafu(source)]
246 error: prost::DecodeError,
247 },
248
249 #[snafu(display("Failed to decode Loki request: {error}"))]
250 DecodeLokiRequest {
251 #[snafu(implicit)]
252 location: Location,
253 #[snafu(source)]
254 error: prost::DecodeError,
255 },
256
257 #[snafu(display(
258 "Unsupported content type 'application/json'. OTLP endpoint only supports 'application/x-protobuf'. Please configure your OTLP exporter to use protobuf encoding."
259 ))]
260 UnsupportedJsonContentType {
261 #[snafu(implicit)]
262 location: Location,
263 },
264
265 #[snafu(display(
266 "OTLP metric input have incompatible existing tables, please refer to docs for details"
267 ))]
268 OtlpMetricModeIncompatible {
269 #[snafu(implicit)]
270 location: Location,
271 },
272
273 #[snafu(display("Common Meta error"))]
274 CommonMeta {
275 #[snafu(implicit)]
276 location: Location,
277 #[snafu(source)]
278 source: common_meta::error::Error,
279 },
280
281 #[snafu(display("Failed to decompress snappy prometheus remote request"))]
282 DecompressSnappyPromRemoteRequest {
283 #[snafu(implicit)]
284 location: Location,
285 #[snafu(source)]
286 error: snap::Error,
287 },
288
289 #[snafu(display("Failed to decompress zstd prometheus remote request"))]
290 DecompressZstdPromRemoteRequest {
291 #[snafu(implicit)]
292 location: Location,
293 #[snafu(source)]
294 error: std::io::Error,
295 },
296
297 #[snafu(display("Failed to compress prometheus remote request"))]
298 CompressPromRemoteRequest {
299 #[snafu(implicit)]
300 location: Location,
301 #[snafu(source)]
302 error: snap::Error,
303 },
304
305 #[snafu(display("Invalid prometheus remote request, msg: {}", msg))]
306 InvalidPromRemoteRequest {
307 msg: String,
308 #[snafu(implicit)]
309 location: Location,
310 },
311
312 #[snafu(display("Invalid prometheus remote read query result, msg: {}", msg))]
313 InvalidPromRemoteReadQueryResult {
314 msg: String,
315 #[snafu(implicit)]
316 location: Location,
317 },
318
319 #[snafu(display("Invalid Flight ticket"))]
320 InvalidFlightTicket {
321 #[snafu(source)]
322 error: api::DecodeError,
323 #[snafu(implicit)]
324 location: Location,
325 },
326
327 #[snafu(display("Tls is required for {}, plain connection is rejected", server))]
328 TlsRequired { server: String },
329
330 #[snafu(display("Failed to get user info"))]
331 Auth {
332 #[snafu(implicit)]
333 location: Location,
334 source: auth::error::Error,
335 },
336
337 #[snafu(display("Not found http or grpc authorization header"))]
338 NotFoundAuthHeader {},
339
340 #[snafu(display("Not found influx http authorization info"))]
341 NotFoundInfluxAuth {},
342
343 #[snafu(display("Unsupported http auth scheme, name: {}", name))]
344 UnsupportedAuthScheme { name: String },
345
346 #[snafu(display("Invalid visibility ASCII chars"))]
347 InvalidAuthHeaderInvisibleASCII {
348 #[snafu(source)]
349 error: hyper::header::ToStrError,
350 #[snafu(implicit)]
351 location: Location,
352 },
353
354 #[snafu(display("Invalid utf-8 value"))]
355 InvalidAuthHeaderInvalidUtf8Value {
356 #[snafu(source)]
357 error: FromUtf8Error,
358 #[snafu(implicit)]
359 location: Location,
360 },
361
362 #[snafu(display("Invalid http authorization header"))]
363 InvalidAuthHeader {
364 #[snafu(implicit)]
365 location: Location,
366 },
367
368 #[snafu(display("Invalid base64 value"))]
369 InvalidBase64Value {
370 #[snafu(source)]
371 error: DecodeError,
372 #[snafu(implicit)]
373 location: Location,
374 },
375
376 #[snafu(display("Invalid utf-8 value"))]
377 InvalidUtf8Value {
378 #[snafu(source)]
379 error: FromUtf8Error,
380 #[snafu(implicit)]
381 location: Location,
382 },
383
384 #[snafu(display("Invalid http header value"))]
385 InvalidHeaderValue {
386 #[snafu(source)]
387 error: InvalidHeaderValue,
388 #[snafu(implicit)]
389 location: Location,
390 },
391
392 #[snafu(display("Error accessing catalog"))]
393 Catalog {
394 source: catalog::error::Error,
395 #[snafu(implicit)]
396 location: Location,
397 },
398
399 #[snafu(display("Cannot find requested table: {}.{}.{}", catalog, schema, table))]
400 TableNotFound {
401 catalog: String,
402 schema: String,
403 table: String,
404 #[snafu(implicit)]
405 location: Location,
406 },
407
408 #[cfg(feature = "mem-prof")]
409 #[snafu(display("Failed to dump profile data"))]
410 DumpProfileData {
411 #[snafu(implicit)]
412 location: Location,
413 source: common_mem_prof::error::Error,
414 },
415
416 #[snafu(display("Invalid prepare statement: {}", err_msg))]
417 InvalidPrepareStatement {
418 err_msg: String,
419 #[snafu(implicit)]
420 location: Location,
421 },
422
423 #[snafu(display("Failed to build HTTP response"))]
424 BuildHttpResponse {
425 #[snafu(source)]
426 error: http::Error,
427 #[snafu(implicit)]
428 location: Location,
429 },
430
431 #[snafu(display("Failed to parse PromQL: {query:?}"))]
432 ParsePromQL {
433 query: Box<PromQuery>,
434 #[snafu(implicit)]
435 location: Location,
436 source: query::error::Error,
437 },
438
439 #[snafu(display("Failed to parse timestamp: {}", timestamp))]
440 ParseTimestamp {
441 timestamp: String,
442 #[snafu(implicit)]
443 location: Location,
444 #[snafu(source)]
445 error: query::error::Error,
446 },
447
448 #[snafu(display("Failed to infer parameter types"))]
449 InferParameterTypes {
450 #[snafu(implicit)]
451 location: Location,
452 #[snafu(source)]
453 error: query::error::Error,
454 },
455
456 #[snafu(display("{}", reason))]
457 UnexpectedResult {
458 reason: String,
459 #[snafu(implicit)]
460 location: Location,
461 },
462
463 #[snafu(display("Other error"))]
466 Other {
467 source: BoxedError,
468 #[snafu(implicit)]
469 location: Location,
470 },
471
472 #[snafu(display("Failed to join task"))]
473 JoinTask {
474 #[snafu(source)]
475 error: tokio::task::JoinError,
476 #[snafu(implicit)]
477 location: Location,
478 },
479
480 #[cfg(feature = "pprof")]
481 #[snafu(display("Failed to dump pprof data"))]
482 DumpPprof { source: common_pprof::error::Error },
483
484 #[cfg(not(windows))]
485 #[snafu(display("Failed to update jemalloc metrics"))]
486 UpdateJemallocMetrics {
487 #[snafu(source)]
488 error: tikv_jemalloc_ctl::Error,
489 #[snafu(implicit)]
490 location: Location,
491 },
492
493 #[snafu(display("DataFrame operation error"))]
494 DataFrame {
495 #[snafu(source)]
496 error: datafusion::error::DataFusionError,
497 #[snafu(implicit)]
498 location: Location,
499 },
500
501 #[snafu(display("Failed to convert scalar value"))]
502 ConvertScalarValue {
503 source: datatypes::error::Error,
504 #[snafu(implicit)]
505 location: Location,
506 },
507
508 #[snafu(display("Expected type: {:?}, actual: {:?}", expected, actual))]
509 PreparedStmtTypeMismatch {
510 expected: ConcreteDataType,
511 actual: opensrv_mysql::ColumnType,
512 #[snafu(implicit)]
513 location: Location,
514 },
515
516 #[snafu(display(
517 "Column: {}, {} incompatible, expected: {}, actual: {}",
518 column_name,
519 datatype,
520 expected,
521 actual
522 ))]
523 IncompatibleSchema {
524 column_name: String,
525 datatype: String,
526 expected: i32,
527 actual: i32,
528 #[snafu(implicit)]
529 location: Location,
530 },
531
532 #[snafu(display("Failed to convert to json"))]
533 ToJson {
534 #[snafu(source)]
535 error: serde_json::error::Error,
536 #[snafu(implicit)]
537 location: Location,
538 },
539
540 #[snafu(display("Failed to parse payload as json"))]
541 ParseJson {
542 #[snafu(source)]
543 error: serde_json::error::Error,
544 #[snafu(implicit)]
545 location: Location,
546 },
547
548 #[snafu(display("Invalid Loki labels: {}", msg))]
549 InvalidLokiLabels {
550 msg: String,
551 #[snafu(implicit)]
552 location: Location,
553 },
554
555 #[snafu(display("Invalid Loki JSON request: {}", msg))]
556 InvalidLokiPayload {
557 msg: String,
558 #[snafu(implicit)]
559 location: Location,
560 },
561
562 #[snafu(display("Unsupported content type: {:?}", content_type))]
563 UnsupportedContentType {
564 content_type: ContentType,
565 #[snafu(implicit)]
566 location: Location,
567 },
568
569 #[snafu(display("Failed to decode url"))]
570 UrlDecode {
571 #[snafu(source)]
572 error: FromUtf8Error,
573 #[snafu(implicit)]
574 location: Location,
575 },
576
577 #[snafu(display("Failed to convert Mysql value, error: {}", err_msg))]
578 MysqlValueConversion {
579 err_msg: String,
580 #[snafu(implicit)]
581 location: Location,
582 },
583
584 #[snafu(display("Invalid table name"))]
585 InvalidTableName {
586 #[snafu(source)]
587 error: tonic::metadata::errors::ToStrError,
588 #[snafu(implicit)]
589 location: Location,
590 },
591
592 #[snafu(display("Failed to initialize a watcher for file {}", path))]
593 FileWatch {
594 path: String,
595 #[snafu(source)]
596 error: notify::Error,
597 },
598
599 #[snafu(display("Timestamp overflow: {}", error))]
600 TimestampOverflow {
601 error: String,
602 #[snafu(implicit)]
603 location: Location,
604 },
605
606 #[snafu(display("Unsupported json data type for tag: {} {}", key, ty))]
607 UnsupportedJsonDataTypeForTag {
608 key: String,
609 ty: String,
610 #[snafu(implicit)]
611 location: Location,
612 },
613
614 #[snafu(display("Convert SQL value error"))]
615 ConvertSqlValue {
616 source: datatypes::error::Error,
617 #[snafu(implicit)]
618 location: Location,
619 },
620
621 #[snafu(display("Prepare statement not found: {}", name))]
622 PrepareStatementNotFound {
623 name: String,
624 #[snafu(implicit)]
625 location: Location,
626 },
627
628 #[snafu(display("Invalid elasticsearch input, reason: {}", reason))]
629 InvalidElasticsearchInput {
630 reason: String,
631 #[snafu(implicit)]
632 location: Location,
633 },
634
635 #[snafu(display("Invalid Jaeger query, reason: {}", reason))]
636 InvalidJaegerQuery {
637 reason: String,
638 #[snafu(implicit)]
639 location: Location,
640 },
641
642 #[snafu(display("DataFusion error"))]
643 DataFusion {
644 #[snafu(source)]
645 error: DataFusionError,
646 #[snafu(implicit)]
647 location: Location,
648 },
649
650 #[snafu(display("Failed to handle otel-arrow request, error message: {}", err_msg))]
651 HandleOtelArrowRequest {
652 err_msg: String,
653 #[snafu(implicit)]
654 location: Location,
655 },
656
657 #[snafu(display("Unknown hint: {}", hint))]
658 UnknownHint { hint: String },
659
660 #[snafu(display("Query has been cancelled"))]
661 Cancelled {
662 #[snafu(implicit)]
663 location: Location,
664 },
665
666 #[snafu(display("Service suspended"))]
667 Suspended {
668 #[snafu(implicit)]
669 location: Location,
670 },
671
672 #[snafu(transparent)]
673 GreptimeProto {
674 source: api::error::Error,
675 #[snafu(implicit)]
676 location: Location,
677 },
678}
679
680pub type Result<T, E = Error> = std::result::Result<T, E>;
681
682impl ErrorExt for Error {
683 fn status_code(&self) -> StatusCode {
684 use Error::*;
685 match self {
686 Internal { .. }
687 | InternalIo { .. }
688 | TokioIo { .. }
689 | StartHttp { .. }
690 | StartGrpc { .. }
691 | TcpBind { .. }
692 | BuildHttpResponse { .. }
693 | Arrow { .. }
694 | FileWatch { .. } => StatusCode::Internal,
695
696 AddressBind { .. }
697 | AlreadyStarted { .. }
698 | InvalidPromRemoteReadQueryResult { .. }
699 | OtlpMetricModeIncompatible { .. } => StatusCode::IllegalState,
700
701 UnsupportedDataType { .. } => StatusCode::Unsupported,
702
703 #[cfg(not(windows))]
704 UpdateJemallocMetrics { .. } => StatusCode::Internal,
705
706 CollectRecordbatch { .. } => StatusCode::EngineExecuteQuery,
707
708 ExecuteQuery { source, .. }
709 | ExecutePlan { source, .. }
710 | ExecuteGrpcQuery { source, .. }
711 | ExecuteGrpcRequest { source, .. }
712 | CheckDatabaseValidity { source, .. } => source.status_code(),
713
714 Pipeline { source, .. } => source.status_code(),
715 CommonMeta { source, .. } => source.status_code(),
716
717 NotSupported { .. }
718 | InvalidParameter { .. }
719 | InvalidQuery { .. }
720 | InfluxdbLineProtocol { .. }
721 | InvalidOpentsdbJsonRequest { .. }
722 | DecodePromRemoteRequest { .. }
723 | DecodeOtlpRequest { .. }
724 | DecodeLokiRequest { .. }
725 | UnsupportedJsonContentType { .. }
726 | CompressPromRemoteRequest { .. }
727 | DecompressSnappyPromRemoteRequest { .. }
728 | DecompressZstdPromRemoteRequest { .. }
729 | InvalidPromRemoteRequest { .. }
730 | InvalidFlightTicket { .. }
731 | InvalidPrepareStatement { .. }
732 | InferParameterTypes { .. }
733 | DataFrame { .. }
734 | PreparedStmtTypeMismatch { .. }
735 | TimePrecision { .. }
736 | UrlDecode { .. }
737 | IncompatibleSchema { .. }
738 | MysqlValueConversion { .. }
739 | ParseJson { .. }
740 | InvalidLokiLabels { .. }
741 | InvalidLokiPayload { .. }
742 | UnsupportedContentType { .. }
743 | TimestampOverflow { .. }
744 | UnsupportedJsonDataTypeForTag { .. }
745 | InvalidTableName { .. }
746 | PrepareStatementNotFound { .. }
747 | FailedToParseQuery { .. }
748 | InvalidElasticsearchInput { .. }
749 | InvalidJaegerQuery { .. }
750 | ParseTimestamp { .. }
751 | UnknownHint { .. } => StatusCode::InvalidArguments,
752
753 Catalog { source, .. } => source.status_code(),
754 RowWriter { source, .. } => source.status_code(),
755
756 TlsRequired { .. } => StatusCode::Unknown,
757 Auth { source, .. } => source.status_code(),
758 DescribeStatement { source } => source.status_code(),
759
760 NotFoundAuthHeader { .. } | NotFoundInfluxAuth { .. } => StatusCode::AuthHeaderNotFound,
761 InvalidAuthHeaderInvisibleASCII { .. }
762 | UnsupportedAuthScheme { .. }
763 | InvalidAuthHeader { .. }
764 | InvalidBase64Value { .. }
765 | InvalidAuthHeaderInvalidUtf8Value { .. } => StatusCode::InvalidAuthHeader,
766
767 TableNotFound { .. } => StatusCode::TableNotFound,
768
769 #[cfg(feature = "mem-prof")]
770 DumpProfileData { source, .. } => source.status_code(),
771
772 InvalidUtf8Value { .. } | InvalidHeaderValue { .. } => StatusCode::InvalidArguments,
773
774 TooManyConcurrentRequests { .. } => StatusCode::RuntimeResourcesExhausted,
775
776 ParsePromQL { source, .. } => source.status_code(),
777 Other { source, .. } => source.status_code(),
778
779 UnexpectedResult { .. } => StatusCode::Unexpected,
780
781 JoinTask { error, .. } => {
782 if error.is_cancelled() {
783 StatusCode::Cancelled
784 } else if error.is_panic() {
785 StatusCode::Unexpected
786 } else {
787 StatusCode::Unknown
788 }
789 }
790
791 #[cfg(feature = "pprof")]
792 DumpPprof { source, .. } => source.status_code(),
793
794 ConvertScalarValue { source, .. } => source.status_code(),
795
796 ToJson { .. } | DataFusion { .. } => StatusCode::Internal,
797
798 ConvertSqlValue { source, .. } => source.status_code(),
799
800 HandleOtelArrowRequest { .. } => StatusCode::Internal,
801
802 Cancelled { .. } => StatusCode::Cancelled,
803
804 Suspended { .. } => StatusCode::Suspended,
805
806 MemoryLimitExceeded { .. } => StatusCode::RateLimited,
807
808 GreptimeProto { source, .. } => source.status_code(),
809 }
810 }
811
812 fn as_any(&self) -> &dyn Any {
813 self
814 }
815}
816
817define_into_tonic_status!(Error);
818
819impl From<std::io::Error> for Error {
820 fn from(e: std::io::Error) -> Self {
821 Error::InternalIo { error: e }
822 }
823}
824
825fn log_error_if_necessary(error: &Error) {
826 if error.status_code().should_log_error() {
827 error!(error; "Failed to handle HTTP request ");
828 } else {
829 warn!(error; "Failed to handle HTTP request ");
830 }
831}
832
833impl IntoResponse for Error {
834 fn into_response(self) -> Response {
835 let error_msg = self.output_msg();
836 let status = status_code_to_http_status(&self.status_code());
837
838 log_error_if_necessary(&self);
839
840 let body = Json(json!({
841 "error": error_msg,
842 }));
843 (status, body).into_response()
844 }
845}
846
847pub fn status_code_to_http_status(status_code: &StatusCode) -> HttpStatusCode {
849 match status_code {
850 StatusCode::Success => HttpStatusCode::OK,
851
852 StatusCode::Cancelled | StatusCode::DeadlineExceeded => HttpStatusCode::GATEWAY_TIMEOUT,
855
856 StatusCode::Unsupported
857 | StatusCode::InvalidArguments
858 | StatusCode::InvalidSyntax
859 | StatusCode::RequestOutdated
860 | StatusCode::RegionAlreadyExists
861 | StatusCode::TableColumnExists
862 | StatusCode::TableAlreadyExists
863 | StatusCode::RegionNotFound
864 | StatusCode::DatabaseNotFound
865 | StatusCode::TableNotFound
866 | StatusCode::TableColumnNotFound
867 | StatusCode::PlanQuery
868 | StatusCode::DatabaseAlreadyExists
869 | StatusCode::TriggerAlreadyExists
870 | StatusCode::TriggerNotFound
871 | StatusCode::FlowNotFound
872 | StatusCode::FlowAlreadyExists => HttpStatusCode::BAD_REQUEST,
873
874 StatusCode::AuthHeaderNotFound
875 | StatusCode::InvalidAuthHeader
876 | StatusCode::UserNotFound
877 | StatusCode::UnsupportedPasswordType
878 | StatusCode::UserPasswordMismatch
879 | StatusCode::RegionReadonly => HttpStatusCode::UNAUTHORIZED,
880
881 StatusCode::PermissionDenied | StatusCode::AccessDenied => HttpStatusCode::FORBIDDEN,
882
883 StatusCode::RateLimited => HttpStatusCode::TOO_MANY_REQUESTS,
884
885 StatusCode::RegionNotReady
886 | StatusCode::TableUnavailable
887 | StatusCode::RegionBusy
888 | StatusCode::StorageUnavailable
889 | StatusCode::External
890 | StatusCode::Suspended => HttpStatusCode::SERVICE_UNAVAILABLE,
891
892 StatusCode::Internal
893 | StatusCode::Unexpected
894 | StatusCode::IllegalState
895 | StatusCode::Unknown
896 | StatusCode::RuntimeResourcesExhausted
897 | StatusCode::EngineExecuteQuery => HttpStatusCode::INTERNAL_SERVER_ERROR,
898 }
899}