1use crate::httpx;
20use crate::tracingcomponent::MetricsName;
21use http::StatusCode;
22use serde_json::Value;
23use std::collections::HashMap;
24use std::error::Error as StdError;
25use std::fmt::{Display, Formatter};
26
27pub type Result<T> = std::result::Result<T, Error>;
28
29#[derive(Debug, Clone, PartialEq)]
30pub struct Error {
31 inner: ErrorImpl,
32}
33
34impl Display for Error {
35 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
36 write!(f, "{}", self.inner.kind)
37 }
38}
39
40impl StdError for Error {}
41
42impl Error {
43 pub(crate) fn new_server_error(e: ServerError) -> Error {
44 Self {
45 inner: ErrorImpl {
46 kind: Box::new(ErrorKind::Server(e)),
47 },
48 }
49 }
50
51 pub(crate) fn new_resource_error(e: ResourceError) -> Error {
52 Self {
53 inner: ErrorImpl {
54 kind: Box::new(ErrorKind::Resource(e)),
55 },
56 }
57 }
58
59 pub(crate) fn new_message_error(
60 msg: impl Into<String>,
61 endpoint: impl Into<Option<String>>,
62 statement: impl Into<Option<String>>,
63 client_context_id: impl Into<Option<String>>,
64 ) -> Error {
65 Self {
66 inner: ErrorImpl {
67 kind: Box::new(ErrorKind::Message {
68 msg: msg.into(),
69 endpoint: endpoint.into(),
70 statement: statement.into(),
71 client_context_id: client_context_id.into(),
72 }),
73 },
74 }
75 }
76
77 pub(crate) fn new_encoding_error(msg: impl Into<String>) -> Error {
78 Self {
79 inner: ErrorImpl {
80 kind: Box::new(ErrorKind::Encoding { msg: msg.into() }),
81 },
82 }
83 }
84
85 pub(crate) fn new_invalid_argument_error(
86 msg: impl Into<String>,
87 arg: impl Into<Option<String>>,
88 ) -> Self {
89 Self {
90 inner: ErrorImpl {
91 kind: Box::new(ErrorKind::InvalidArgument {
92 msg: msg.into(),
93 arg: arg.into(),
94 }),
95 },
96 }
97 }
98
99 pub(crate) fn new_http_error(
100 error: httpx::error::Error,
101 endpoint: impl Into<String>,
102 statement: impl Into<Option<String>>,
103 client_context_id: impl Into<Option<String>>,
104 ) -> Self {
105 Self {
106 inner: ErrorImpl {
107 kind: Box::new(ErrorKind::Http {
108 error,
109 endpoint: endpoint.into(),
110 statement: statement.into(),
111 client_context_id: client_context_id.into(),
112 }),
113 },
114 }
115 }
116
117 pub fn kind(&self) -> &ErrorKind {
118 &self.inner.kind
119 }
120}
121
122#[derive(Debug, Clone)]
123struct ErrorImpl {
124 kind: Box<ErrorKind>,
125}
126
127impl PartialEq for ErrorImpl {
128 fn eq(&self, other: &Self) -> bool {
129 self.kind == other.kind
130 }
131}
132
133#[derive(Clone, Debug, PartialEq, Eq)]
134#[non_exhaustive]
135pub enum ErrorKind {
136 Server(ServerError),
137 #[non_exhaustive]
138 Http {
139 error: httpx::error::Error,
140 endpoint: String,
141 statement: Option<String>,
142 client_context_id: Option<String>,
143 },
144 Resource(ResourceError),
145 #[non_exhaustive]
146 Message {
147 msg: String,
148 endpoint: Option<String>,
149 statement: Option<String>,
150 client_context_id: Option<String>,
151 },
152 #[non_exhaustive]
153 InvalidArgument {
154 msg: String,
155 arg: Option<String>,
156 },
157 #[non_exhaustive]
158 Encoding {
159 msg: String,
160 },
161}
162
163impl Display for ErrorKind {
164 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
165 match self {
166 ErrorKind::Server(e) => write!(f, "{e}"),
167 ErrorKind::Resource(e) => write!(f, "{e}"),
168 ErrorKind::InvalidArgument { msg, arg } => {
169 let base_msg = format!("invalid argument: {msg}");
170 if let Some(arg) = arg {
171 write!(f, "{base_msg}, arg: {arg}")
172 } else {
173 write!(f, "{base_msg}")
174 }
175 }
176 ErrorKind::Encoding { msg } => write!(f, "encoding error: {msg}"),
177 ErrorKind::Http {
178 error,
179 endpoint,
180 statement,
181 client_context_id,
182 } => {
183 write!(f, "http error {error}: endpoint: {endpoint}")?;
184 if let Some(statement) = statement {
185 write!(f, ", statement: {statement}")?;
186 }
187 if let Some(client_context_id) = client_context_id {
188 write!(f, ", client context id: {client_context_id}")?;
189 }
190 Ok(())
191 }
192 ErrorKind::Message {
193 msg,
194 endpoint,
195 statement,
196 client_context_id,
197 } => {
198 write!(f, "{msg}")?;
199 if let Some(endpoint) = endpoint {
200 write!(f, ", endpoint: {endpoint}")?;
201 }
202 if let Some(statement) = statement {
203 write!(f, ", statement: {statement}")?;
204 }
205 if let Some(client_context_id) = client_context_id {
206 write!(f, ", client context id: {client_context_id}")?;
207 }
208 Ok(())
209 }
210 }
211 }
212}
213
214#[derive(Clone, Debug, PartialEq, Eq)]
215pub struct ServerError {
216 kind: ServerErrorKind,
217
218 endpoint: String,
219 status_code: StatusCode,
220 code: u32,
221 msg: String,
222 retry: bool,
223
224 statement: Option<String>,
225 client_context_id: Option<String>,
226
227 all_error_descs: Vec<ErrorDesc>,
228}
229
230impl ServerError {
231 pub(crate) fn new(
232 kind: ServerErrorKind,
233 endpoint: impl Into<String>,
234 status_code: StatusCode,
235 code: u32,
236 retry: bool,
237 msg: impl Into<String>,
238 ) -> Self {
239 Self {
240 kind,
241 endpoint: endpoint.into(),
242 status_code,
243 code,
244 msg: msg.into(),
245 retry,
246 statement: None,
247 client_context_id: None,
248 all_error_descs: vec![],
249 }
250 }
251
252 pub fn kind(&self) -> &ServerErrorKind {
253 &self.kind
254 }
255
256 pub fn endpoint(&self) -> &str {
257 &self.endpoint
258 }
259
260 pub fn statement(&self) -> Option<&str> {
261 self.statement.as_deref()
262 }
263
264 pub fn status_code(&self) -> StatusCode {
265 self.status_code
266 }
267
268 pub fn client_context_id(&self) -> Option<&str> {
269 self.client_context_id.as_deref()
270 }
271
272 pub fn code(&self) -> u32 {
273 self.code
274 }
275
276 pub fn msg(&self) -> &str {
277 &self.msg
278 }
279
280 pub fn retry(&self) -> bool {
281 self.retry
282 }
283
284 pub fn all_error_descs(&self) -> &[ErrorDesc] {
285 &self.all_error_descs
286 }
287
288 pub(crate) fn with_statement(mut self, statement: impl Into<String>) -> Self {
289 self.statement = Some(statement.into());
290 self
291 }
292
293 pub(crate) fn with_client_context_id(mut self, client_context_id: impl Into<String>) -> Self {
294 self.client_context_id = Some(client_context_id.into());
295 self
296 }
297
298 pub(crate) fn with_error_descs(mut self, error_descs: Vec<ErrorDesc>) -> Self {
299 self.all_error_descs = error_descs;
300 self
301 }
302}
303
304impl Display for ServerError {
305 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
306 write!(
307 f,
308 "server error of kind: {} code: {}, msg: {}",
309 self.kind, self.code, self.msg
310 )?;
311
312 if let Some(client_context_id) = &self.client_context_id {
313 write!(f, ", client context id: {client_context_id}")?;
314 }
315 if let Some(statement) = &self.statement {
316 write!(f, ", statement: {statement}")?;
317 }
318
319 write!(
320 f,
321 ", endpoint: {}, status code: {}",
322 self.endpoint, self.status_code
323 )?;
324
325 if !self.all_error_descs.is_empty() {
326 write!(f, ", all error descriptions: {:?}", self.all_error_descs)?;
327 }
328
329 Ok(())
330 }
331}
332
333#[derive(Clone, Debug, PartialEq, Eq)]
334#[non_exhaustive]
335pub struct ResourceError {
336 cause: ServerError,
337 bucket_name: Option<String>,
338 scope_name: Option<String>,
339 collection_name: Option<String>,
340 index_name: Option<String>,
341}
342
343impl ResourceError {
344 pub(crate) fn new(cause: ServerError) -> Self {
345 match cause.kind {
346 ServerErrorKind::CollectionNotFound => Self::parse_resource_not_found(cause),
347 ServerErrorKind::ScopeNotFound => Self::parse_resource_not_found(cause),
348 ServerErrorKind::AuthenticationFailure => Self::parse_auth_failure(cause),
349 ServerErrorKind::IndexNotFound => Self::parse_index_not_found_or_exists(cause),
350 ServerErrorKind::IndexExists => Self::parse_index_not_found_or_exists(cause),
351 _ => Self {
352 cause,
353 bucket_name: None,
354 scope_name: None,
355 collection_name: None,
356 index_name: None,
357 },
358 }
359 }
360
361 pub fn cause(&self) -> &ServerError {
362 &self.cause
363 }
364
365 pub fn bucket_name(&self) -> Option<&str> {
366 self.bucket_name.as_deref()
367 }
368
369 pub fn scope_name(&self) -> Option<&str> {
370 self.scope_name.as_deref()
371 }
372
373 pub fn collection_name(&self) -> Option<&str> {
374 self.collection_name.as_deref()
375 }
376
377 pub fn index_name(&self) -> Option<&str> {
378 self.index_name.as_deref()
379 }
380
381 fn parse_index_not_found_or_exists(cause: ServerError) -> ResourceError {
382 let msg = cause.msg.clone();
383 let mut fields = msg.split_whitespace();
384
385 while let Some(field) = fields.next() {
388 if field == "index" {
389 return ResourceError {
390 cause,
391 bucket_name: None,
392 scope_name: None,
393 collection_name: None,
394 index_name: Some(fields.next().unwrap().to_string()),
395 };
396 }
397 }
398
399 ResourceError {
400 cause,
401 bucket_name: None,
402 scope_name: None,
403 collection_name: None,
404 index_name: None,
405 }
406 }
407
408 fn parse_resource_not_found(cause: ServerError) -> ResourceError {
409 let msg = cause.msg.clone();
410 let mut fields = msg.split_whitespace();
411 let path = fields.find(|f| f.contains('.') && f.contains(':'));
413
414 if let Some(p) = path {
415 if let Some(trimmed_path) = p.split(':').nth(1) {
416 let fields: Vec<&str> = trimmed_path.split('.').collect();
417
418 if cause.kind == ServerErrorKind::ScopeNotFound {
419 let bucket_name = fields[0..fields.len() - 1].join(".");
421 let scope_name = fields[fields.len() - 1];
422
423 return ResourceError {
424 cause,
425 bucket_name: Some(bucket_name),
426 scope_name: Some(scope_name.to_string()),
427 collection_name: None,
428 index_name: None,
429 };
430 } else if cause.kind == ServerErrorKind::CollectionNotFound {
431 let bucket_name = fields[0..fields.len() - 2].join(".");
433 let scope_name = fields[fields.len() - 2];
434 let collection_name = fields[fields.len() - 1];
435
436 return ResourceError {
437 cause,
438 bucket_name: Some(bucket_name),
439 scope_name: Some(scope_name.to_string()),
440 collection_name: Some(collection_name.to_string()),
441 index_name: None,
442 };
443 }
444 }
445 }
446
447 ResourceError {
448 cause,
449 bucket_name: None,
450 scope_name: None,
451 collection_name: None,
452 index_name: None,
453 }
454 }
455
456 fn parse_auth_failure(cause: ServerError) -> Self {
457 let msg = &cause.msg;
458 let mut fields = msg.split_whitespace();
459 let path = fields.find(|f| f.contains(':'));
460
461 if let Some(p) = path {
462 if let Some(trimmed_path) = p.split(':').nth(1) {
463 let (bucket_name, scope_name, collection_name) = if trimmed_path.contains('`') {
464 let fields: Vec<&str> = trimmed_path.split('`').collect();
467
468 let bucket_name = fields[1];
469
470 let (scope_name, collection_name) = if fields[2].is_empty() {
471 (None, None)
472 } else {
473 let scope_and_col = fields[2];
476 let fields: Vec<&str> = scope_and_col.split('.').collect();
477 let (scope, collection) = if fields.len() >= 3 {
478 (Some(fields[1].to_string()), Some(fields[2].to_string()))
479 } else {
480 (None, None)
481 };
482
483 (scope, collection)
484 };
485
486 (Some(bucket_name.to_string()), scope_name, collection_name)
487 } else {
488 let fields: Vec<&str> = trimmed_path.split('.').collect();
489
490 let bucket_name = fields[0];
491
492 let (scope_name, collection_name) = if fields.len() >= 3 {
493 (Some(fields[1].to_string()), Some(fields[2].to_string()))
494 } else {
495 (None, None)
496 };
497
498 (Some(bucket_name.to_string()), scope_name, collection_name)
499 };
500
501 return ResourceError {
502 cause,
503 bucket_name,
504 scope_name,
505 collection_name,
506 index_name: None,
507 };
508 }
509 }
510
511 ResourceError {
512 cause,
513 bucket_name: None,
514 scope_name: None,
515 collection_name: None,
516 index_name: None,
517 }
518 }
519}
520
521impl Display for ResourceError {
522 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
523 write!(f, "resource error caused by: {}", self.cause)?;
524
525 if let Some(bucket_name) = &self.bucket_name {
526 write!(f, ", bucket: {bucket_name}")?;
527 }
528 if let Some(scope_name) = &self.scope_name {
529 write!(f, ", scope: {scope_name}")?;
530 }
531 if let Some(collection_name) = &self.collection_name {
532 write!(f, ", collection: {collection_name}")?;
533 }
534 if let Some(index_name) = &self.index_name {
535 write!(f, ", index: {index_name}")?;
536 }
537
538 Ok(())
539 }
540}
541
542impl StdError for ResourceError {}
543
544#[derive(Clone, Debug, PartialEq, Eq)]
545#[non_exhaustive]
546pub struct ErrorDesc {
547 kind: ServerErrorKind,
548
549 code: u32,
550 message: String,
551 retry: bool,
552 reason: HashMap<String, Value>,
553}
554
555impl ErrorDesc {
556 pub fn new(
557 kind: ServerErrorKind,
558 code: u32,
559 message: String,
560 retry: bool,
561 reason: HashMap<String, Value>,
562 ) -> Self {
563 Self {
564 kind,
565 code,
566 message,
567 retry,
568 reason,
569 }
570 }
571
572 pub fn kind(&self) -> &ServerErrorKind {
573 &self.kind
574 }
575
576 pub fn code(&self) -> u32 {
577 self.code
578 }
579
580 pub fn message(&self) -> &str {
581 &self.message
582 }
583
584 pub fn retry(&self) -> bool {
585 self.retry
586 }
587
588 pub fn reason(&self) -> &HashMap<String, Value> {
589 &self.reason
590 }
591}
592
593impl Display for ErrorDesc {
594 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
595 write!(
596 f,
597 "error description of kind: {}, code: {}, message: {}, retry: {}, reason: {:?}",
598 self.kind, self.code, self.message, self.retry, self.reason
599 )
600 }
601}
602
603#[derive(Clone, Debug, PartialEq, Eq)]
604#[non_exhaustive]
605pub enum ServerErrorKind {
606 ParsingFailure,
607 Internal,
608 AuthenticationFailure,
609 CasMismatch,
610 DocNotFound,
611 DocExists,
612 PlanningFailure,
613 IndexFailure,
614 PreparedStatementFailure,
615 DMLFailure,
616 Timeout,
617 IndexExists,
618 IndexNotFound,
619 WriteInReadOnlyMode,
620 ScopeNotFound,
621 CollectionNotFound,
622 InvalidArgument { argument: String, reason: String },
623 BuildAlreadyInProgress,
624 Unknown,
625}
626
627impl Display for ServerErrorKind {
628 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
629 match self {
630 ServerErrorKind::ParsingFailure => write!(f, "parsing failure"),
631 ServerErrorKind::Internal => write!(f, "internal server error"),
632 ServerErrorKind::AuthenticationFailure => write!(f, "authentication failure"),
633 ServerErrorKind::CasMismatch => write!(f, "cas mismatch"),
634 ServerErrorKind::DocNotFound => write!(f, "doc not found"),
635 ServerErrorKind::DocExists => write!(f, "doc exists"),
636 ServerErrorKind::PlanningFailure => write!(f, "planning failure"),
637 ServerErrorKind::IndexFailure => write!(f, "index failure"),
638 ServerErrorKind::PreparedStatementFailure => write!(f, "prepared statement failure"),
639 ServerErrorKind::DMLFailure => write!(
640 f,
641 "data service returned an error during execution of DML statement"
642 ),
643 ServerErrorKind::Timeout => write!(f, "server timeout"),
644 ServerErrorKind::IndexExists => write!(f, "index exists"),
645 ServerErrorKind::IndexNotFound => write!(f, "index not found"),
646 ServerErrorKind::WriteInReadOnlyMode => {
647 write!(f, "write statement used in a read-only query")
648 }
649 ServerErrorKind::ScopeNotFound => write!(f, "scope not found"),
650 ServerErrorKind::CollectionNotFound => write!(f, "collection not found"),
651 ServerErrorKind::InvalidArgument { argument, reason } => write!(
652 f,
653 "server invalid argument: (argument: {argument}, reason: {reason})"
654 ),
655 ServerErrorKind::BuildAlreadyInProgress => write!(f, "build already in progress"),
656 ServerErrorKind::Unknown => write!(f, "unknown query error"),
657 }
658 }
659}
660
661impl Error {
662 pub fn is_parsing_failure(&self) -> bool {
663 matches!(
664 self.kind(),
665 ErrorKind::Server(ServerError {
666 kind: ServerErrorKind::ParsingFailure,
667 ..
668 })
669 )
670 }
671
672 pub fn is_internal(&self) -> bool {
673 matches!(
674 self.kind(),
675 ErrorKind::Server(ServerError {
676 kind: ServerErrorKind::Internal,
677 ..
678 })
679 )
680 }
681
682 pub fn is_authentication_failure(&self) -> bool {
683 matches!(
684 self.kind(),
685 ErrorKind::Server(ServerError {
686 kind: ServerErrorKind::AuthenticationFailure,
687 ..
688 })
689 )
690 }
691
692 pub fn is_cas_mismatch(&self) -> bool {
693 matches!(
694 self.kind(),
695 ErrorKind::Server(ServerError {
696 kind: ServerErrorKind::CasMismatch,
697 ..
698 })
699 )
700 }
701
702 pub fn is_doc_not_found(&self) -> bool {
703 matches!(
704 self.kind(),
705 ErrorKind::Server(ServerError {
706 kind: ServerErrorKind::DocNotFound,
707 ..
708 })
709 )
710 }
711
712 pub fn is_doc_exists(&self) -> bool {
713 matches!(
714 self.kind(),
715 ErrorKind::Server(ServerError {
716 kind: ServerErrorKind::DocExists,
717 ..
718 })
719 )
720 }
721
722 pub fn is_planning_failure(&self) -> bool {
723 matches!(
724 self.kind(),
725 ErrorKind::Server(ServerError {
726 kind: ServerErrorKind::PlanningFailure,
727 ..
728 })
729 )
730 }
731
732 pub fn is_index_failure(&self) -> bool {
733 matches!(
734 self.kind(),
735 ErrorKind::Server(ServerError {
736 kind: ServerErrorKind::IndexFailure,
737 ..
738 })
739 )
740 }
741
742 pub fn is_prepared_statement_failure(&self) -> bool {
743 matches!(
744 self.kind(),
745 ErrorKind::Server(ServerError {
746 kind: ServerErrorKind::PreparedStatementFailure,
747 ..
748 })
749 )
750 }
751
752 pub fn is_dml_failure(&self) -> bool {
753 matches!(
754 self.kind(),
755 ErrorKind::Server(ServerError {
756 kind: ServerErrorKind::DMLFailure,
757 ..
758 })
759 )
760 }
761
762 pub fn is_server_timeout(&self) -> bool {
763 matches!(
764 self.kind(),
765 ErrorKind::Server(ServerError {
766 kind: ServerErrorKind::Timeout,
767 ..
768 })
769 )
770 }
771
772 pub fn is_write_in_read_only_mode(&self) -> bool {
773 matches!(
774 self.kind(),
775 ErrorKind::Server(ServerError {
776 kind: ServerErrorKind::WriteInReadOnlyMode,
777 ..
778 })
779 )
780 }
781
782 pub fn is_invalid_argument(&self) -> bool {
783 matches!(
784 self.kind(),
785 ErrorKind::Server(ServerError {
786 kind: ServerErrorKind::InvalidArgument { .. },
787 ..
788 })
789 )
790 }
791
792 pub fn is_build_already_in_progress(&self) -> bool {
793 matches!(
794 self.kind(),
795 ErrorKind::Server(ServerError {
796 kind: ServerErrorKind::BuildAlreadyInProgress,
797 ..
798 })
799 )
800 }
801
802 pub fn is_scope_not_found(&self) -> bool {
803 matches!(
804 self.kind(),
805 ErrorKind::Resource(ResourceError {
806 cause: ServerError {
807 kind: ServerErrorKind::ScopeNotFound,
808 ..
809 },
810 ..
811 })
812 ) || matches!(
813 self.kind(),
814 ErrorKind::Server(ServerError {
815 kind: ServerErrorKind::ScopeNotFound,
816 ..
817 })
818 )
819 }
820
821 pub fn is_collection_not_found(&self) -> bool {
822 matches!(
823 self.kind(),
824 ErrorKind::Resource(ResourceError {
825 cause: ServerError {
826 kind: ServerErrorKind::CollectionNotFound,
827 ..
828 },
829 ..
830 })
831 ) || matches!(
832 self.kind(),
833 ErrorKind::Server(ServerError {
834 kind: ServerErrorKind::CollectionNotFound,
835 ..
836 })
837 )
838 }
839
840 pub fn is_index_not_found(&self) -> bool {
841 matches!(
842 self.kind(),
843 ErrorKind::Resource(ResourceError {
844 cause: ServerError {
845 kind: ServerErrorKind::IndexNotFound,
846 ..
847 },
848 ..
849 })
850 ) || matches!(
851 self.kind(),
852 ErrorKind::Server(ServerError {
853 kind: ServerErrorKind::IndexNotFound,
854 ..
855 })
856 )
857 }
858
859 pub fn is_index_exists(&self) -> bool {
860 matches!(
861 self.kind(),
862 ErrorKind::Resource(ResourceError {
863 cause: ServerError {
864 kind: ServerErrorKind::IndexExists,
865 ..
866 },
867 ..
868 })
869 ) || matches!(
870 self.kind(),
871 ErrorKind::Server(ServerError {
872 kind: ServerErrorKind::IndexExists,
873 ..
874 })
875 )
876 }
877}
878
879impl MetricsName for Error {
880 fn metrics_name(&self) -> &'static str {
881 match self.kind() {
882 ErrorKind::Server(e) => e.kind().metrics_name(),
883 ErrorKind::Resource(e) => e.cause().kind().metrics_name(),
884 ErrorKind::Http { error, .. } => error.metrics_name(),
885 ErrorKind::Message { .. } => "queryx._OTHER",
886 ErrorKind::InvalidArgument { .. } => "queryx.InvalidArgument",
887 ErrorKind::Encoding { .. } => "queryx.Encoding",
888 }
889 }
890}
891
892impl MetricsName for ServerErrorKind {
893 fn metrics_name(&self) -> &'static str {
894 match self {
895 ServerErrorKind::ParsingFailure => "queryx.ParsingFailure",
896 ServerErrorKind::Internal => "queryx.Internal",
897 ServerErrorKind::AuthenticationFailure => "queryx.AuthenticationFailure",
898 ServerErrorKind::CasMismatch => "queryx.CasMismatch",
899 ServerErrorKind::DocNotFound => "queryx.DocNotFound",
900 ServerErrorKind::DocExists => "queryx.DocExists",
901 ServerErrorKind::PlanningFailure => "queryx.PlanningFailure",
902 ServerErrorKind::IndexFailure => "queryx.IndexFailure",
903 ServerErrorKind::PreparedStatementFailure => "queryx.PreparedStatementFailure",
904 ServerErrorKind::DMLFailure => "queryx.DMLFailure",
905 ServerErrorKind::Timeout => "queryx.Timeout",
906 ServerErrorKind::IndexExists => "queryx.IndexExists",
907 ServerErrorKind::IndexNotFound => "queryx.IndexNotFound",
908 ServerErrorKind::WriteInReadOnlyMode => "queryx.WriteInReadOnlyMode",
909 ServerErrorKind::ScopeNotFound => "queryx.ScopeNotFound",
910 ServerErrorKind::CollectionNotFound => "queryx.CollectionNotFound",
911 ServerErrorKind::InvalidArgument { .. } => "queryx.InvalidArgument",
912 ServerErrorKind::BuildAlreadyInProgress => "queryx.BuildAlreadyInProgress",
913 ServerErrorKind::Unknown => "queryx._OTHER",
914 }
915 }
916}