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("{} 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 #[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
814pub fn status_code_to_http_status(status_code: &StatusCode) -> HttpStatusCode {
816 match status_code {
817 StatusCode::Success => HttpStatusCode::OK,
818
819 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}