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