servers/
error.rs

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