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