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
223 statement: Option<String>,
224 client_context_id: Option<String>,
225
226 all_error_descs: Vec<ErrorDesc>,
227}
228
229impl ServerError {
230 pub(crate) fn new(
231 kind: ServerErrorKind,
232 endpoint: impl Into<String>,
233 status_code: StatusCode,
234 code: u32,
235 msg: impl Into<String>,
236 ) -> Self {
237 Self {
238 kind,
239 endpoint: endpoint.into(),
240 status_code,
241 code,
242 msg: msg.into(),
243 statement: None,
244 client_context_id: None,
245 all_error_descs: vec![],
246 }
247 }
248
249 pub fn kind(&self) -> &ServerErrorKind {
250 &self.kind
251 }
252
253 pub fn endpoint(&self) -> &str {
254 &self.endpoint
255 }
256
257 pub fn statement(&self) -> Option<&str> {
258 self.statement.as_deref()
259 }
260
261 pub fn status_code(&self) -> StatusCode {
262 self.status_code
263 }
264
265 pub fn client_context_id(&self) -> Option<&str> {
266 self.client_context_id.as_deref()
267 }
268
269 pub fn code(&self) -> u32 {
270 self.code
271 }
272
273 pub fn msg(&self) -> &str {
274 &self.msg
275 }
276
277 pub fn all_error_descs(&self) -> &[ErrorDesc] {
278 &self.all_error_descs
279 }
280
281 pub(crate) fn with_statement(mut self, statement: impl Into<String>) -> Self {
282 self.statement = Some(statement.into());
283 self
284 }
285
286 pub(crate) fn with_client_context_id(mut self, client_context_id: impl Into<String>) -> Self {
287 self.client_context_id = Some(client_context_id.into());
288 self
289 }
290
291 pub(crate) fn with_error_descs(mut self, error_descs: Vec<ErrorDesc>) -> Self {
292 self.all_error_descs = error_descs;
293 self
294 }
295}
296
297impl Display for ServerError {
298 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
299 write!(
300 f,
301 "server error of kind: {} code: {}, msg: {}",
302 self.kind, self.code, self.msg
303 )?;
304
305 if let Some(client_context_id) = &self.client_context_id {
306 write!(f, ", client context id: {client_context_id}")?;
307 }
308 if let Some(statement) = &self.statement {
309 write!(f, ", statement: {statement}")?;
310 }
311
312 write!(
313 f,
314 ", endpoint: {}, status code: {}",
315 self.endpoint, self.status_code
316 )?;
317
318 if !self.all_error_descs.is_empty() {
319 write!(f, ", all error descriptions: {:?}", self.all_error_descs)?;
320 }
321
322 Ok(())
323 }
324}
325
326#[derive(Clone, Debug, PartialEq, Eq)]
327#[non_exhaustive]
328pub struct ResourceError {
329 cause: ServerError,
330 bucket_name: Option<String>,
331 scope_name: Option<String>,
332 collection_name: Option<String>,
333 index_name: Option<String>,
334}
335
336impl ResourceError {
337 pub(crate) fn new(cause: ServerError) -> Self {
338 match cause.kind {
339 ServerErrorKind::CollectionNotFound => Self::parse_resource_not_found(cause),
340 ServerErrorKind::ScopeNotFound => Self::parse_resource_not_found(cause),
341 ServerErrorKind::AuthenticationFailure => Self::parse_auth_failure(cause),
342 ServerErrorKind::IndexNotFound => Self::parse_index_not_found_or_exists(cause),
343 ServerErrorKind::IndexExists => Self::parse_index_not_found_or_exists(cause),
344 _ => Self {
345 cause,
346 bucket_name: None,
347 scope_name: None,
348 collection_name: None,
349 index_name: None,
350 },
351 }
352 }
353
354 pub fn cause(&self) -> &ServerError {
355 &self.cause
356 }
357
358 pub fn bucket_name(&self) -> Option<&str> {
359 self.bucket_name.as_deref()
360 }
361
362 pub fn scope_name(&self) -> Option<&str> {
363 self.scope_name.as_deref()
364 }
365
366 pub fn collection_name(&self) -> Option<&str> {
367 self.collection_name.as_deref()
368 }
369
370 pub fn index_name(&self) -> Option<&str> {
371 self.index_name.as_deref()
372 }
373
374 fn parse_index_not_found_or_exists(cause: ServerError) -> ResourceError {
375 let msg = cause.msg.clone();
376 let mut fields = msg.split_whitespace();
377
378 while let Some(field) = fields.next() {
381 if field == "index" {
382 return ResourceError {
383 cause,
384 bucket_name: None,
385 scope_name: None,
386 collection_name: None,
387 index_name: Some(fields.next().unwrap().to_string()),
388 };
389 }
390 }
391
392 ResourceError {
393 cause,
394 bucket_name: None,
395 scope_name: None,
396 collection_name: None,
397 index_name: None,
398 }
399 }
400
401 fn parse_resource_not_found(cause: ServerError) -> ResourceError {
402 let msg = cause.msg.clone();
403 let mut fields = msg.split_whitespace();
404 let path = fields.find(|f| f.contains('.') && f.contains(':'));
406
407 if let Some(p) = path {
408 if let Some(trimmed_path) = p.split(':').nth(1) {
409 let fields: Vec<&str> = trimmed_path.split('.').collect();
410
411 if cause.kind == ServerErrorKind::ScopeNotFound {
412 let bucket_name = fields[0..fields.len() - 1].join(".");
414 let scope_name = fields[fields.len() - 1];
415
416 return ResourceError {
417 cause,
418 bucket_name: Some(bucket_name),
419 scope_name: Some(scope_name.to_string()),
420 collection_name: None,
421 index_name: None,
422 };
423 } else if cause.kind == ServerErrorKind::CollectionNotFound {
424 let bucket_name = fields[0..fields.len() - 2].join(".");
426 let scope_name = fields[fields.len() - 2];
427 let collection_name = fields[fields.len() - 1];
428
429 return ResourceError {
430 cause,
431 bucket_name: Some(bucket_name),
432 scope_name: Some(scope_name.to_string()),
433 collection_name: Some(collection_name.to_string()),
434 index_name: None,
435 };
436 }
437 }
438 }
439
440 ResourceError {
441 cause,
442 bucket_name: None,
443 scope_name: None,
444 collection_name: None,
445 index_name: None,
446 }
447 }
448
449 fn parse_auth_failure(cause: ServerError) -> Self {
450 let msg = &cause.msg;
451 let mut fields = msg.split_whitespace();
452 let path = fields.find(|f| f.contains(':'));
453
454 if let Some(p) = path {
455 if let Some(trimmed_path) = p.split(':').nth(1) {
456 let (bucket_name, scope_name, collection_name) = if trimmed_path.contains('`') {
457 let fields: Vec<&str> = trimmed_path.split('`').collect();
460
461 let bucket_name = fields[1];
462
463 let (scope_name, collection_name) = if fields[2].is_empty() {
464 (None, None)
465 } else {
466 let scope_and_col = fields[2];
469 let fields: Vec<&str> = scope_and_col.split('.').collect();
470 let (scope, collection) = if fields.len() >= 3 {
471 (Some(fields[1].to_string()), Some(fields[2].to_string()))
472 } else {
473 (None, None)
474 };
475
476 (scope, collection)
477 };
478
479 (Some(bucket_name.to_string()), scope_name, collection_name)
480 } else {
481 let fields: Vec<&str> = trimmed_path.split('.').collect();
482
483 let bucket_name = fields[0];
484
485 let (scope_name, collection_name) = if fields.len() >= 3 {
486 (Some(fields[1].to_string()), Some(fields[2].to_string()))
487 } else {
488 (None, None)
489 };
490
491 (Some(bucket_name.to_string()), scope_name, collection_name)
492 };
493
494 return ResourceError {
495 cause,
496 bucket_name,
497 scope_name,
498 collection_name,
499 index_name: None,
500 };
501 }
502 }
503
504 ResourceError {
505 cause,
506 bucket_name: None,
507 scope_name: None,
508 collection_name: None,
509 index_name: None,
510 }
511 }
512}
513
514impl Display for ResourceError {
515 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
516 write!(f, "resource error caused by: {}", self.cause)?;
517
518 if let Some(bucket_name) = &self.bucket_name {
519 write!(f, ", bucket: {bucket_name}")?;
520 }
521 if let Some(scope_name) = &self.scope_name {
522 write!(f, ", scope: {scope_name}")?;
523 }
524 if let Some(collection_name) = &self.collection_name {
525 write!(f, ", collection: {collection_name}")?;
526 }
527 if let Some(index_name) = &self.index_name {
528 write!(f, ", index: {index_name}")?;
529 }
530
531 Ok(())
532 }
533}
534
535impl StdError for ResourceError {}
536
537#[derive(Clone, Debug, PartialEq, Eq)]
538#[non_exhaustive]
539pub struct ErrorDesc {
540 kind: ServerErrorKind,
541
542 code: u32,
543 message: String,
544 retry: bool,
545 reason: HashMap<String, Value>,
546}
547
548impl ErrorDesc {
549 pub fn new(
550 kind: ServerErrorKind,
551 code: u32,
552 message: String,
553 retry: bool,
554 reason: HashMap<String, Value>,
555 ) -> Self {
556 Self {
557 kind,
558 code,
559 message,
560 retry,
561 reason,
562 }
563 }
564
565 pub fn kind(&self) -> &ServerErrorKind {
566 &self.kind
567 }
568
569 pub fn code(&self) -> u32 {
570 self.code
571 }
572
573 pub fn message(&self) -> &str {
574 &self.message
575 }
576
577 pub fn retry(&self) -> bool {
578 self.retry
579 }
580
581 pub fn reason(&self) -> &HashMap<String, Value> {
582 &self.reason
583 }
584}
585
586impl Display for ErrorDesc {
587 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
588 write!(
589 f,
590 "error description of kind: {}, code: {}, message: {}, retry: {}, reason: {:?}",
591 self.kind, self.code, self.message, self.retry, self.reason
592 )
593 }
594}
595
596#[derive(Clone, Debug, PartialEq, Eq)]
597#[non_exhaustive]
598pub enum ServerErrorKind {
599 ParsingFailure,
600 Internal,
601 AuthenticationFailure,
602 CasMismatch,
603 DocNotFound,
604 DocExists,
605 PlanningFailure,
606 IndexFailure,
607 PreparedStatementFailure,
608 DMLFailure,
609 Timeout,
610 IndexExists,
611 IndexNotFound,
612 WriteInReadOnlyMode,
613 ScopeNotFound,
614 CollectionNotFound,
615 InvalidArgument { argument: String, reason: String },
616 BuildAlreadyInProgress,
617 Unknown,
618}
619
620impl Display for ServerErrorKind {
621 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
622 match self {
623 ServerErrorKind::ParsingFailure => write!(f, "parsing failure"),
624 ServerErrorKind::Internal => write!(f, "internal server error"),
625 ServerErrorKind::AuthenticationFailure => write!(f, "authentication failure"),
626 ServerErrorKind::CasMismatch => write!(f, "cas mismatch"),
627 ServerErrorKind::DocNotFound => write!(f, "doc not found"),
628 ServerErrorKind::DocExists => write!(f, "doc exists"),
629 ServerErrorKind::PlanningFailure => write!(f, "planning failure"),
630 ServerErrorKind::IndexFailure => write!(f, "index failure"),
631 ServerErrorKind::PreparedStatementFailure => write!(f, "prepared statement failure"),
632 ServerErrorKind::DMLFailure => write!(
633 f,
634 "data service returned an error during execution of DML statement"
635 ),
636 ServerErrorKind::Timeout => write!(f, "server timeout"),
637 ServerErrorKind::IndexExists => write!(f, "index exists"),
638 ServerErrorKind::IndexNotFound => write!(f, "index not found"),
639 ServerErrorKind::WriteInReadOnlyMode => {
640 write!(f, "write statement used in a read-only query")
641 }
642 ServerErrorKind::ScopeNotFound => write!(f, "scope not found"),
643 ServerErrorKind::CollectionNotFound => write!(f, "collection not found"),
644 ServerErrorKind::InvalidArgument { argument, reason } => write!(
645 f,
646 "server invalid argument: (argument: {argument}, reason: {reason})"
647 ),
648 ServerErrorKind::BuildAlreadyInProgress => write!(f, "build already in progress"),
649 ServerErrorKind::Unknown => write!(f, "unknown query error"),
650 }
651 }
652}
653
654impl Error {
655 pub fn is_parsing_failure(&self) -> bool {
656 matches!(
657 self.kind(),
658 ErrorKind::Server(ServerError {
659 kind: ServerErrorKind::ParsingFailure,
660 ..
661 })
662 )
663 }
664
665 pub fn is_internal(&self) -> bool {
666 matches!(
667 self.kind(),
668 ErrorKind::Server(ServerError {
669 kind: ServerErrorKind::Internal,
670 ..
671 })
672 )
673 }
674
675 pub fn is_authentication_failure(&self) -> bool {
676 matches!(
677 self.kind(),
678 ErrorKind::Server(ServerError {
679 kind: ServerErrorKind::AuthenticationFailure,
680 ..
681 })
682 )
683 }
684
685 pub fn is_cas_mismatch(&self) -> bool {
686 matches!(
687 self.kind(),
688 ErrorKind::Server(ServerError {
689 kind: ServerErrorKind::CasMismatch,
690 ..
691 })
692 )
693 }
694
695 pub fn is_doc_not_found(&self) -> bool {
696 matches!(
697 self.kind(),
698 ErrorKind::Server(ServerError {
699 kind: ServerErrorKind::DocNotFound,
700 ..
701 })
702 )
703 }
704
705 pub fn is_doc_exists(&self) -> bool {
706 matches!(
707 self.kind(),
708 ErrorKind::Server(ServerError {
709 kind: ServerErrorKind::DocExists,
710 ..
711 })
712 )
713 }
714
715 pub fn is_planning_failure(&self) -> bool {
716 matches!(
717 self.kind(),
718 ErrorKind::Server(ServerError {
719 kind: ServerErrorKind::PlanningFailure,
720 ..
721 })
722 )
723 }
724
725 pub fn is_index_failure(&self) -> bool {
726 matches!(
727 self.kind(),
728 ErrorKind::Server(ServerError {
729 kind: ServerErrorKind::IndexFailure,
730 ..
731 })
732 )
733 }
734
735 pub fn is_prepared_statement_failure(&self) -> bool {
736 matches!(
737 self.kind(),
738 ErrorKind::Server(ServerError {
739 kind: ServerErrorKind::PreparedStatementFailure,
740 ..
741 })
742 )
743 }
744
745 pub fn is_dml_failure(&self) -> bool {
746 matches!(
747 self.kind(),
748 ErrorKind::Server(ServerError {
749 kind: ServerErrorKind::DMLFailure,
750 ..
751 })
752 )
753 }
754
755 pub fn is_server_timeout(&self) -> bool {
756 matches!(
757 self.kind(),
758 ErrorKind::Server(ServerError {
759 kind: ServerErrorKind::Timeout,
760 ..
761 })
762 )
763 }
764
765 pub fn is_write_in_read_only_mode(&self) -> bool {
766 matches!(
767 self.kind(),
768 ErrorKind::Server(ServerError {
769 kind: ServerErrorKind::WriteInReadOnlyMode,
770 ..
771 })
772 )
773 }
774
775 pub fn is_invalid_argument(&self) -> bool {
776 matches!(
777 self.kind(),
778 ErrorKind::Server(ServerError {
779 kind: ServerErrorKind::InvalidArgument { .. },
780 ..
781 })
782 )
783 }
784
785 pub fn is_build_already_in_progress(&self) -> bool {
786 matches!(
787 self.kind(),
788 ErrorKind::Server(ServerError {
789 kind: ServerErrorKind::BuildAlreadyInProgress,
790 ..
791 })
792 )
793 }
794
795 pub fn is_scope_not_found(&self) -> bool {
796 matches!(
797 self.kind(),
798 ErrorKind::Resource(ResourceError {
799 cause: ServerError {
800 kind: ServerErrorKind::ScopeNotFound,
801 ..
802 },
803 ..
804 })
805 ) || matches!(
806 self.kind(),
807 ErrorKind::Server(ServerError {
808 kind: ServerErrorKind::ScopeNotFound,
809 ..
810 })
811 )
812 }
813
814 pub fn is_collection_not_found(&self) -> bool {
815 matches!(
816 self.kind(),
817 ErrorKind::Resource(ResourceError {
818 cause: ServerError {
819 kind: ServerErrorKind::CollectionNotFound,
820 ..
821 },
822 ..
823 })
824 ) || matches!(
825 self.kind(),
826 ErrorKind::Server(ServerError {
827 kind: ServerErrorKind::CollectionNotFound,
828 ..
829 })
830 )
831 }
832
833 pub fn is_index_not_found(&self) -> bool {
834 matches!(
835 self.kind(),
836 ErrorKind::Resource(ResourceError {
837 cause: ServerError {
838 kind: ServerErrorKind::IndexNotFound,
839 ..
840 },
841 ..
842 })
843 ) || matches!(
844 self.kind(),
845 ErrorKind::Server(ServerError {
846 kind: ServerErrorKind::IndexNotFound,
847 ..
848 })
849 )
850 }
851
852 pub fn is_index_exists(&self) -> bool {
853 matches!(
854 self.kind(),
855 ErrorKind::Resource(ResourceError {
856 cause: ServerError {
857 kind: ServerErrorKind::IndexExists,
858 ..
859 },
860 ..
861 })
862 ) || matches!(
863 self.kind(),
864 ErrorKind::Server(ServerError {
865 kind: ServerErrorKind::IndexExists,
866 ..
867 })
868 )
869 }
870}
871
872impl MetricsName for Error {
873 fn metrics_name(&self) -> &'static str {
874 match self.kind() {
875 ErrorKind::Server(e) => e.kind().metrics_name(),
876 ErrorKind::Resource(e) => e.cause().kind().metrics_name(),
877 ErrorKind::Http { error, .. } => error.metrics_name(),
878 ErrorKind::Message { .. } => "queryx._OTHER",
879 ErrorKind::InvalidArgument { .. } => "queryx.InvalidArgument",
880 ErrorKind::Encoding { .. } => "queryx.Encoding",
881 }
882 }
883}
884
885impl MetricsName for ServerErrorKind {
886 fn metrics_name(&self) -> &'static str {
887 match self {
888 ServerErrorKind::ParsingFailure => "queryx.ParsingFailure",
889 ServerErrorKind::Internal => "queryx.Internal",
890 ServerErrorKind::AuthenticationFailure => "queryx.AuthenticationFailure",
891 ServerErrorKind::CasMismatch => "queryx.CasMismatch",
892 ServerErrorKind::DocNotFound => "queryx.DocNotFound",
893 ServerErrorKind::DocExists => "queryx.DocExists",
894 ServerErrorKind::PlanningFailure => "queryx.PlanningFailure",
895 ServerErrorKind::IndexFailure => "queryx.IndexFailure",
896 ServerErrorKind::PreparedStatementFailure => "queryx.PreparedStatementFailure",
897 ServerErrorKind::DMLFailure => "queryx.DMLFailure",
898 ServerErrorKind::Timeout => "queryx.Timeout",
899 ServerErrorKind::IndexExists => "queryx.IndexExists",
900 ServerErrorKind::IndexNotFound => "queryx.IndexNotFound",
901 ServerErrorKind::WriteInReadOnlyMode => "queryx.WriteInReadOnlyMode",
902 ServerErrorKind::ScopeNotFound => "queryx.ScopeNotFound",
903 ServerErrorKind::CollectionNotFound => "queryx.CollectionNotFound",
904 ServerErrorKind::InvalidArgument { .. } => "queryx.InvalidArgument",
905 ServerErrorKind::BuildAlreadyInProgress => "queryx.BuildAlreadyInProgress",
906 ServerErrorKind::Unknown => "queryx._OTHER",
907 }
908 }
909}