1#[cfg(test)]
9mod tests;
10
11use candid::CandidType;
12use icydb_diagnostic_code as diagnostic_code;
13use serde::Deserialize;
14use std::fmt;
15
16pub(crate) const COMPACT_QUERY_DIAGNOSTIC_MESSAGE: &str = "query diagnostic";
17const COMPACT_RUNTIME_DIAGNOSTIC_MESSAGE: &str = "runtime diagnostic";
18const COMPACT_STORE_DIAGNOSTIC_MESSAGE: &str = "store diagnostic";
19const COMPACT_INDEX_DIAGNOSTIC_MESSAGE: &str = "index diagnostic";
20const COMPACT_SERIALIZE_DIAGNOSTIC_MESSAGE: &str = "serialize diagnostic";
21const COMPACT_IDENTITY_DIAGNOSTIC_MESSAGE: &str = "identity diagnostic";
22
23const fn compact_message_for(_class: ErrorClass, origin: ErrorOrigin) -> &'static str {
24 match origin {
25 ErrorOrigin::Serialize => COMPACT_SERIALIZE_DIAGNOSTIC_MESSAGE,
26 ErrorOrigin::Store => COMPACT_STORE_DIAGNOSTIC_MESSAGE,
27 ErrorOrigin::Index => COMPACT_INDEX_DIAGNOSTIC_MESSAGE,
28 ErrorOrigin::Identity => COMPACT_IDENTITY_DIAGNOSTIC_MESSAGE,
29 ErrorOrigin::Query | ErrorOrigin::Planner | ErrorOrigin::Response => {
30 COMPACT_QUERY_DIAGNOSTIC_MESSAGE
31 }
32 ErrorOrigin::Cursor
33 | ErrorOrigin::Recovery
34 | ErrorOrigin::Executor
35 | ErrorOrigin::Interface => COMPACT_RUNTIME_DIAGNOSTIC_MESSAGE,
36 }
37}
38
39#[derive(Clone, Copy, Debug)]
135pub(crate) struct MutationDiagnosticContext {
136 fingerprint_method: u8,
137 accepted_schema_fingerprint: [u8; 16],
138 entity_tag: u64,
139 operation: diagnostic_code::DiagnosticMutationOperation,
140 batch_position: Option<u32>,
141}
142
143impl MutationDiagnosticContext {
144 #[must_use]
146 pub(crate) const fn new(
147 fingerprint_method: u8,
148 accepted_schema_fingerprint: [u8; 16],
149 entity_tag: u64,
150 operation: diagnostic_code::DiagnosticMutationOperation,
151 batch_position: u32,
152 ) -> Self {
153 Self {
154 fingerprint_method,
155 accepted_schema_fingerprint,
156 entity_tag,
157 operation,
158 batch_position: Some(batch_position),
159 }
160 }
161
162 #[must_use]
164 pub(crate) const fn operation_only(
165 fingerprint_method: u8,
166 accepted_schema_fingerprint: [u8; 16],
167 entity_tag: u64,
168 operation: diagnostic_code::DiagnosticMutationOperation,
169 ) -> Self {
170 Self {
171 fingerprint_method,
172 accepted_schema_fingerprint,
173 entity_tag,
174 operation,
175 batch_position: None,
176 }
177 }
178
179 fn facts(self, field_id: Option<u32>) -> Vec<(diagnostic_code::DiagnosticFactTag, u64)> {
180 let mut facts = Vec::with_capacity(
181 5 + usize::from(field_id.is_some()) + usize::from(self.batch_position.is_some()),
182 );
183 append_accepted_schema_facts(
184 &mut facts,
185 self.fingerprint_method,
186 self.accepted_schema_fingerprint,
187 );
188 facts.push((
189 diagnostic_code::DiagnosticFactTag::EntityTag,
190 self.entity_tag,
191 ));
192 if let Some(field_id) = field_id {
193 facts.push((
194 diagnostic_code::DiagnosticFactTag::FieldId,
195 u64::from(field_id),
196 ));
197 }
198 self.append_operation_facts(&mut facts);
199 facts
200 }
201
202 #[must_use]
203 pub(crate) const fn entity_tag(self) -> u64 {
204 self.entity_tag
205 }
206
207 fn append_operation_facts(self, facts: &mut Vec<(diagnostic_code::DiagnosticFactTag, u64)>) {
208 facts.push((
209 diagnostic_code::DiagnosticFactTag::MutationOperation,
210 self.operation.raw(),
211 ));
212 if let Some(batch_position) = self.batch_position {
213 facts.push((
214 diagnostic_code::DiagnosticFactTag::BatchPosition,
215 u64::from(batch_position),
216 ));
217 }
218 }
219}
220
221pub struct DiagnosticFactDetail {
223 diagnostic: diagnostic_code::Diagnostic,
224 facts: Vec<(diagnostic_code::DiagnosticFactTag, u64)>,
225}
226
227pub struct InternalError {
235 pub(crate) class: ErrorClass,
236 pub(crate) origin: ErrorOrigin,
237
238 pub(crate) detail: Option<ErrorDetail>,
241}
242
243#[expect(
244 clippy::missing_const_for_fn,
245 reason = "internal error constructors stay non-const so compact diagnostic construction does not force const churn across subsystem helper seams"
246)]
247impl InternalError {
248 #[must_use]
252 #[cold]
253 #[inline(never)]
254 pub fn new(class: ErrorClass, origin: ErrorOrigin) -> Self {
255 let detail = match (class, origin) {
256 (ErrorClass::Corruption, ErrorOrigin::Store) => {
257 Some(ErrorDetail::Store(StoreError::Corrupt))
258 }
259 (ErrorClass::InvariantViolation, ErrorOrigin::Store) => {
260 Some(ErrorDetail::Store(StoreError::InvariantViolation))
261 }
262 _ => None,
263 };
264
265 Self {
266 class,
267 origin,
268 detail,
269 }
270 }
271
272 #[must_use]
274 pub const fn class(&self) -> ErrorClass {
275 self.class
276 }
277
278 #[must_use]
280 pub const fn origin(&self) -> ErrorOrigin {
281 self.origin
282 }
283
284 #[must_use]
286 pub const fn message(&self) -> &'static str {
287 compact_message_for(self.class, self.origin)
288 }
289
290 #[must_use]
292 pub const fn detail(&self) -> Option<&ErrorDetail> {
293 self.detail.as_ref()
294 }
295
296 #[must_use]
298 pub fn diagnostic(&self) -> diagnostic_code::Diagnostic {
299 diagnostic_code::Diagnostic::new(
300 self.diagnostic_code(),
301 self.origin.diagnostic_origin(),
302 self.detail
303 .as_ref()
304 .and_then(ErrorDetail::diagnostic_detail),
305 )
306 }
307
308 #[must_use]
310 #[cold]
311 #[inline(never)]
312 pub fn diagnostic_facts(&self) -> Vec<(diagnostic_code::DiagnosticFactTag, u64)> {
313 self.detail
314 .as_ref()
315 .map_or_else(Vec::new, ErrorDetail::diagnostic_facts)
316 }
317
318 #[must_use]
320 pub fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
321 self.detail.as_ref().map_or_else(
322 || self.class.diagnostic_code(self.origin),
323 ErrorDetail::diagnostic_code,
324 )
325 }
326
327 #[must_use]
329 pub fn into_message(self) -> String {
330 self.message().to_string()
331 }
332
333 #[cold]
335 #[inline(never)]
336 pub(crate) fn classified(class: ErrorClass, origin: ErrorOrigin) -> Self {
337 Self::new(class, origin)
338 }
339
340 #[cold]
341 #[inline(never)]
342 fn with_diagnostic_facts(
343 class: ErrorClass,
344 origin: ErrorOrigin,
345 detail: Option<diagnostic_code::DiagnosticDetail>,
346 facts: Vec<(diagnostic_code::DiagnosticFactTag, u64)>,
347 ) -> Self {
348 let code = match detail {
349 Some(detail) => detail.diagnostic_code(),
350 None => class.diagnostic_code(origin),
351 };
352 let diagnostic = diagnostic_code::Diagnostic::new(code, origin.diagnostic_origin(), detail);
353 if diagnostic_code::validate_known_diagnostic_fact_schema(
354 diagnostic.error_code(),
355 facts.as_slice(),
356 )
357 .is_err()
358 {
359 return Self::new(ErrorClass::InvariantViolation, origin);
360 }
361 Self {
362 class,
363 origin,
364 detail: Some(ErrorDetail::DiagnosticFacts(Box::new(
365 DiagnosticFactDetail { diagnostic, facts },
366 ))),
367 }
368 }
369
370 #[cold]
371 #[inline(never)]
372 fn mutation_boundary_with_facts(
373 class: ErrorClass,
374 boundary: diagnostic_code::RuntimeBoundaryCode,
375 facts: Vec<(diagnostic_code::DiagnosticFactTag, u64)>,
376 ) -> Self {
377 Self::with_diagnostic_facts(
378 class,
379 ErrorOrigin::Executor,
380 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary { boundary }),
381 facts,
382 )
383 }
384
385 #[cold]
386 #[inline(never)]
387 fn exact_key_batch_boundary_with_facts(
388 boundary: diagnostic_code::RuntimeBoundaryCode,
389 facts: Vec<(diagnostic_code::DiagnosticFactTag, u64)>,
390 ) -> Self {
391 Self::with_diagnostic_facts(
392 ErrorClass::Unsupported,
393 ErrorOrigin::Query,
394 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary { boundary }),
395 facts,
396 )
397 }
398
399 pub(crate) fn sql_query_entity_not_found() -> Self {
401 Self::with_diagnostic_facts(
402 ErrorClass::NotFound,
403 ErrorOrigin::Interface,
404 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
405 boundary: diagnostic_code::RuntimeBoundaryCode::SqlQueryEntityNotFound,
406 }),
407 Vec::new(),
408 )
409 }
410
411 #[cold]
413 #[inline(never)]
414 pub(crate) fn execution_budget_exceeded(
415 resource: diagnostic_code::DiagnosticExecutionBudgetResource,
416 limit: u64,
417 observed: u64,
418 scope: diagnostic_code::DiagnosticExecutionBudgetScope,
419 lane: diagnostic_code::DiagnosticExecutionLane,
420 normalized_shape_fingerprint_prefix: u64,
421 ) -> Self {
422 Self::with_diagnostic_facts(
423 ErrorClass::Unsupported,
424 ErrorOrigin::Executor,
425 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
426 boundary: diagnostic_code::RuntimeBoundaryCode::ExecutionBudgetExceeded,
427 }),
428 vec![
429 (
430 diagnostic_code::DiagnosticFactTag::BudgetResource,
431 resource.raw(),
432 ),
433 (diagnostic_code::DiagnosticFactTag::Limit, limit),
434 (diagnostic_code::DiagnosticFactTag::Actual, observed),
435 (
436 diagnostic_code::DiagnosticFactTag::ExecutionBudgetScope,
437 scope.raw(),
438 ),
439 (
440 diagnostic_code::DiagnosticFactTag::ExecutionLane,
441 lane.raw(),
442 ),
443 (
444 diagnostic_code::DiagnosticFactTag::QueryShapeFingerprintPrefix,
445 normalized_shape_fingerprint_prefix,
446 ),
447 ],
448 )
449 }
450
451 #[cold]
453 #[inline(never)]
454 pub(crate) fn relation_budget_exceeded(
455 resource: diagnostic_code::DiagnosticExecutionBudgetResource,
456 limit: u64,
457 observed: u64,
458 ) -> Self {
459 Self::execution_budget_exceeded(
460 resource,
461 limit,
462 observed,
463 diagnostic_code::DiagnosticExecutionBudgetScope::Execution,
464 diagnostic_code::DiagnosticExecutionLane::Mutation,
465 0,
466 )
467 }
468
469 #[cold]
471 #[inline(never)]
472 pub(crate) fn page_unit_too_large(
473 resource: diagnostic_code::DiagnosticExecutionBudgetResource,
474 limit: u64,
475 attempted: u64,
476 ) -> Self {
477 Self::with_diagnostic_facts(
478 ErrorClass::Unsupported,
479 ErrorOrigin::Executor,
480 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
481 boundary: diagnostic_code::RuntimeBoundaryCode::PageUnitTooLarge,
482 }),
483 vec![
484 (
485 diagnostic_code::DiagnosticFactTag::BudgetResource,
486 resource.raw(),
487 ),
488 (diagnostic_code::DiagnosticFactTag::Limit, limit),
489 (diagnostic_code::DiagnosticFactTag::Actual, attempted),
490 ],
491 )
492 }
493
494 #[cold]
500 #[inline(never)]
501 pub(crate) fn with_origin(self, origin: ErrorOrigin) -> Self {
502 match self.detail {
503 Some(ErrorDetail::DiagnosticFacts(mut detail)) => {
504 let leaf = detail.diagnostic.detail().copied();
505 let code = leaf.map_or_else(
506 || self.class.diagnostic_code(origin),
507 diagnostic_code::DiagnosticDetail::diagnostic_code,
508 );
509 let diagnostic =
510 diagnostic_code::Diagnostic::new(code, origin.diagnostic_origin(), leaf);
511 if diagnostic_code::validate_known_diagnostic_fact_schema(
514 diagnostic.error_code(),
515 &detail.facts,
516 )
517 .is_err()
518 {
519 return Self::classified(self.class, origin);
520 }
521 detail.diagnostic = diagnostic;
522
523 Self {
524 class: self.class,
525 origin,
526 detail: Some(ErrorDetail::DiagnosticFacts(detail)),
527 }
528 }
529 _ => Self::classified(self.class, origin),
530 }
531 }
532
533 #[cold]
535 #[inline(never)]
536 pub(crate) fn index_invariant() -> Self {
537 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Index)
538 }
539
540 pub(crate) fn index_key_field_count_exceeds_max(
542 entity_tag: u64,
543 physical_generation: u64,
544 field_count: usize,
545 max_fields: usize,
546 ) -> Self {
547 Self::with_diagnostic_facts(
548 ErrorClass::InvariantViolation,
549 ErrorOrigin::Index,
550 None,
551 vec![
552 (diagnostic_code::DiagnosticFactTag::EntityTag, entity_tag),
553 (
554 diagnostic_code::DiagnosticFactTag::PhysicalGeneration,
555 physical_generation,
556 ),
557 (
558 diagnostic_code::DiagnosticFactTag::ComponentKind,
559 diagnostic_code::DiagnosticComponentKind::IndexKey.raw(),
560 ),
561 (
562 diagnostic_code::DiagnosticFactTag::ActualArity,
563 field_count as u64,
564 ),
565 (
566 diagnostic_code::DiagnosticFactTag::Maximum,
567 max_fields as u64,
568 ),
569 ],
570 )
571 }
572
573 #[cold]
576 #[inline(never)]
577 pub(crate) fn planner_executor_invariant() -> Self {
578 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Planner)
579 }
580
581 #[cold]
584 #[inline(never)]
585 pub(crate) fn query_executor_invariant() -> Self {
586 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Query)
587 }
588
589 #[cold]
592 #[inline(never)]
593 pub(crate) fn cursor_executor_invariant() -> Self {
594 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Cursor)
595 }
596
597 #[cold]
599 #[inline(never)]
600 pub(crate) fn executor_invariant() -> Self {
601 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Executor)
602 }
603
604 #[cold]
606 #[inline(never)]
607 pub(crate) fn executor_internal() -> Self {
608 Self::new(ErrorClass::Internal, ErrorOrigin::Executor)
609 }
610
611 #[cold]
613 #[inline(never)]
614 pub(crate) fn executor_unsupported() -> Self {
615 Self::new(ErrorClass::Unsupported, ErrorOrigin::Executor)
616 }
617
618 #[cold]
620 #[inline(never)]
621 pub(crate) fn mutation_database_owned_field_explicit(
622 context: MutationDiagnosticContext,
623 field_id: u32,
624 ) -> Self {
625 Self::mutation_boundary_with_facts(
626 ErrorClass::Unsupported,
627 diagnostic_code::RuntimeBoundaryCode::MutationDatabaseOwnedFieldExplicit,
628 context.facts(Some(field_id)),
629 )
630 }
631
632 #[must_use]
634 #[cold]
635 #[inline(never)]
636 pub(crate) fn mutation_required_field_missing(
637 context: MutationDiagnosticContext,
638 field_id: u32,
639 ) -> Self {
640 Self::mutation_boundary_with_facts(
641 ErrorClass::Unsupported,
642 diagnostic_code::RuntimeBoundaryCode::MutationRequiredFieldMissing,
643 context.facts(Some(field_id)),
644 )
645 }
646
647 #[must_use]
649 #[cold]
650 #[inline(never)]
651 pub(crate) fn mutation_managed_timestamp_regression(
652 context: MutationDiagnosticContext,
653 ) -> Self {
654 Self::mutation_boundary_with_facts(
655 ErrorClass::InvariantViolation,
656 diagnostic_code::RuntimeBoundaryCode::MutationManagedTimestampRegression,
657 context.facts(None),
658 )
659 }
660
661 pub(crate) fn mutation_constraint_violation(context: AcceptedConstraintFactContext) -> Self {
663 Self::mutation_boundary_with_facts(
664 ErrorClass::InvariantViolation,
665 diagnostic_code::RuntimeBoundaryCode::ConstraintViolation,
666 context.facts(),
667 )
668 }
669
670 pub(crate) fn accepted_row_constraint_program_corrupt() -> Self {
672 Self {
673 class: ErrorClass::Corruption,
674 origin: ErrorOrigin::Executor,
675 detail: Some(ErrorDetail::Executor(
676 ExecutorErrorDetail::AcceptedRowConstraintProgramCorrupt,
677 )),
678 }
679 }
680
681 pub(crate) fn mutation_constraint_activation_write_blocked(
683 context: AcceptedConstraintFactContext,
684 ) -> Self {
685 Self::mutation_boundary_with_facts(
686 ErrorClass::Conflict,
687 diagnostic_code::RuntimeBoundaryCode::ConstraintActivationWriteBlocked,
688 context.facts(),
689 )
690 }
691
692 pub(crate) fn scalar_page_cursor_boundary_order_required() -> Self {
694 Self::query_executor_invariant()
695 }
696
697 pub(crate) fn scalar_page_cursor_boundary_after_ordering_required() -> Self {
699 Self::query_executor_invariant()
700 }
701
702 pub(crate) fn scalar_page_pagination_after_ordering_required() -> Self {
704 Self::query_executor_invariant()
705 }
706
707 pub(crate) fn secondary_index_prefix_spec_required() -> Self {
709 Self::query_executor_invariant()
710 }
711
712 pub(crate) fn index_range_limit_spec_required() -> Self {
714 Self::query_executor_invariant()
715 }
716
717 #[cold]
719 #[inline(never)]
720 pub(crate) fn mutation_atomic_save_duplicate_key(
721 entity_tag: u64,
722 first_position: u32,
723 duplicate_position: u32,
724 ) -> Self {
725 Self::mutation_boundary_with_facts(
726 ErrorClass::Conflict,
727 diagnostic_code::RuntimeBoundaryCode::MutationBatchDuplicateKey,
728 vec![
729 (diagnostic_code::DiagnosticFactTag::EntityTag, entity_tag),
730 (
731 diagnostic_code::DiagnosticFactTag::FirstBatchPosition,
732 u64::from(first_position),
733 ),
734 (
735 diagnostic_code::DiagnosticFactTag::DuplicateBatchPosition,
736 u64::from(duplicate_position),
737 ),
738 ],
739 )
740 }
741
742 #[cold]
744 #[inline(never)]
745 pub(crate) fn mutation_batch_empty() -> Self {
746 Self::mutation_boundary_with_facts(
747 ErrorClass::Unsupported,
748 diagnostic_code::RuntimeBoundaryCode::MutationBatchEmpty,
749 vec![(diagnostic_code::DiagnosticFactTag::ActualCount, 0)],
750 )
751 }
752
753 #[cold]
755 #[inline(never)]
756 pub(crate) fn mutation_batch_too_many_items(actual_count: usize, limit: usize) -> Self {
757 Self::mutation_boundary_with_facts(
758 ErrorClass::Unsupported,
759 diagnostic_code::RuntimeBoundaryCode::MutationBatchTooManyItems,
760 vec![
761 (
762 diagnostic_code::DiagnosticFactTag::ActualCount,
763 actual_count as u64,
764 ),
765 (diagnostic_code::DiagnosticFactTag::Limit, limit as u64),
766 ],
767 )
768 }
769
770 #[cold]
772 #[inline(never)]
773 pub(crate) fn mutation_batch_staged_bytes_exceeded(
774 actual_bytes: Option<usize>,
775 limit: usize,
776 ) -> Self {
777 let mut facts = Vec::with_capacity(1 + usize::from(actual_bytes.is_some()));
778 if let Some(actual_bytes) = actual_bytes {
779 facts.push((
780 diagnostic_code::DiagnosticFactTag::ActualLength,
781 actual_bytes as u64,
782 ));
783 }
784 facts.push((diagnostic_code::DiagnosticFactTag::Limit, limit as u64));
785 Self::mutation_boundary_with_facts(
786 ErrorClass::Unsupported,
787 diagnostic_code::RuntimeBoundaryCode::MutationBatchStagedBytesExceeded,
788 facts,
789 )
790 }
791
792 #[cold]
794 #[inline(never)]
795 pub(crate) fn mutation_batch_result_bytes_exceeded(actual_bytes: usize, limit: usize) -> Self {
796 Self::mutation_boundary_with_facts(
797 ErrorClass::Unsupported,
798 diagnostic_code::RuntimeBoundaryCode::MutationBatchResultBytesExceeded,
799 vec![
800 (
801 diagnostic_code::DiagnosticFactTag::ActualLength,
802 actual_bytes as u64,
803 ),
804 (diagnostic_code::DiagnosticFactTag::Limit, limit as u64),
805 ],
806 )
807 }
808
809 #[cold]
811 #[inline(never)]
812 pub(crate) fn mutation_batch_commit_work_exceeded(
813 actual_units: Option<usize>,
814 limit: usize,
815 ) -> Self {
816 let mut facts = Vec::with_capacity(1 + usize::from(actual_units.is_some()));
817 if let Some(actual_units) = actual_units {
818 facts.push((
819 diagnostic_code::DiagnosticFactTag::ActualCount,
820 actual_units as u64,
821 ));
822 }
823 facts.push((diagnostic_code::DiagnosticFactTag::Limit, limit as u64));
824 Self::mutation_boundary_with_facts(
825 ErrorClass::Unsupported,
826 diagnostic_code::RuntimeBoundaryCode::MutationBatchCommitWorkExceeded,
827 facts,
828 )
829 }
830
831 pub(crate) fn convergence_backlog_pressure(
833 resource: diagnostic_code::DiagnosticBacklogResource,
834 current: u64,
835 proposed: u64,
836 limit: u64,
837 ) -> Self {
838 Self::mutation_boundary_with_facts(
839 ErrorClass::Conflict,
840 diagnostic_code::RuntimeBoundaryCode::ConvergenceBacklogPressure,
841 vec![
842 (
843 diagnostic_code::DiagnosticFactTag::BacklogResource,
844 resource.raw(),
845 ),
846 (diagnostic_code::DiagnosticFactTag::CurrentCount, current),
847 (diagnostic_code::DiagnosticFactTag::ProposedCount, proposed),
848 (diagnostic_code::DiagnosticFactTag::Limit, limit),
849 ],
850 )
851 }
852
853 #[cold]
855 #[inline(never)]
856 pub(crate) fn exact_key_batch_too_many_items(actual_count: usize, limit: usize) -> Self {
857 Self::exact_key_batch_boundary_with_facts(
858 diagnostic_code::RuntimeBoundaryCode::ExactKeyBatchTooManyItems,
859 vec![
860 (
861 diagnostic_code::DiagnosticFactTag::ActualCount,
862 actual_count as u64,
863 ),
864 (diagnostic_code::DiagnosticFactTag::Limit, limit as u64),
865 ],
866 )
867 }
868
869 #[cold]
871 #[inline(never)]
872 pub(crate) fn exact_key_batch_input_bytes_exceeded(actual_bytes: usize, limit: usize) -> Self {
873 Self::exact_key_batch_bytes_exceeded(
874 diagnostic_code::RuntimeBoundaryCode::ExactKeyBatchInputBytesExceeded,
875 actual_bytes,
876 limit,
877 )
878 }
879
880 #[cold]
882 #[inline(never)]
883 pub(crate) fn exact_key_batch_stored_bytes_exceeded(actual_bytes: usize, limit: usize) -> Self {
884 Self::exact_key_batch_bytes_exceeded(
885 diagnostic_code::RuntimeBoundaryCode::ExactKeyBatchStoredBytesExceeded,
886 actual_bytes,
887 limit,
888 )
889 }
890
891 #[cold]
893 #[inline(never)]
894 pub(crate) fn exact_key_batch_result_bytes_exceeded(actual_bytes: usize, limit: usize) -> Self {
895 Self::exact_key_batch_bytes_exceeded(
896 diagnostic_code::RuntimeBoundaryCode::ExactKeyBatchResultBytesExceeded,
897 actual_bytes,
898 limit,
899 )
900 }
901
902 #[cold]
903 #[inline(never)]
904 fn exact_key_batch_bytes_exceeded(
905 boundary: diagnostic_code::RuntimeBoundaryCode,
906 actual_bytes: usize,
907 limit: usize,
908 ) -> Self {
909 Self::exact_key_batch_boundary_with_facts(
910 boundary,
911 vec![
912 (
913 diagnostic_code::DiagnosticFactTag::ActualLength,
914 actual_bytes as u64,
915 ),
916 (diagnostic_code::DiagnosticFactTag::Limit, limit as u64),
917 ],
918 )
919 }
920
921 #[cold]
923 #[inline(never)]
924 pub(crate) fn mutation_batch_store_mismatch(
925 batch_position: u32,
926 expected_entity_tag: u64,
927 actual_entity_tag: u64,
928 ) -> Self {
929 Self::mutation_boundary_with_facts(
930 ErrorClass::Conflict,
931 diagnostic_code::RuntimeBoundaryCode::MutationBatchStoreMismatch,
932 vec![
933 (
934 diagnostic_code::DiagnosticFactTag::BatchPosition,
935 u64::from(batch_position),
936 ),
937 (
938 diagnostic_code::DiagnosticFactTag::ExpectedEntityTag,
939 expected_entity_tag,
940 ),
941 (
942 diagnostic_code::DiagnosticFactTag::ActualEntityTag,
943 actual_entity_tag,
944 ),
945 ],
946 )
947 }
948
949 #[cold]
951 #[inline(never)]
952 pub(crate) fn mutation_batch_too_many_entities(actual_count: usize, limit: usize) -> Self {
953 Self::mutation_boundary_with_facts(
954 ErrorClass::Unsupported,
955 diagnostic_code::RuntimeBoundaryCode::MutationBatchTooManyEntities,
956 vec![
957 (
958 diagnostic_code::DiagnosticFactTag::ActualCount,
959 actual_count as u64,
960 ),
961 (diagnostic_code::DiagnosticFactTag::Limit, limit as u64),
962 ],
963 )
964 }
965
966 #[cold]
968 #[inline(never)]
969 pub(crate) fn planner_invariant() -> Self {
970 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Planner)
971 }
972
973 pub(crate) fn query_invalid_logical_plan() -> Self {
975 Self::planner_invariant()
976 }
977
978 pub(crate) fn store_invariant() -> Self {
980 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Store)
981 }
982
983 #[cold]
985 #[inline(never)]
986 pub(crate) fn store_internal() -> Self {
987 Self::new(ErrorClass::Internal, ErrorOrigin::Store)
988 }
989
990 pub(crate) fn commit_memory_id_unconfigured() -> Self {
992 Self::store_internal()
993 }
994
995 pub(crate) fn commit_store_uninitialized() -> Self {
997 Self::store_invariant()
998 }
999
1000 pub(crate) fn database_incarnation_generation_failed() -> Self {
1002 Self::store_internal()
1003 }
1004
1005 pub(crate) fn database_incarnation_invalid() -> Self {
1007 Self::store_corruption()
1008 }
1009
1010 pub(crate) fn recovery_unsupported_database_format(found: Option<u16>, required: u16) -> Self {
1012 Self {
1013 class: ErrorClass::IncompatiblePersistedFormat,
1014 origin: ErrorOrigin::Recovery,
1015 detail: Some(ErrorDetail::Recovery(
1016 RecoveryErrorDetail::UnsupportedFormatVersion { found, required },
1017 )),
1018 }
1019 }
1020
1021 pub(crate) fn recovery_malformed_database_format_marker(
1023 reason: RecoveryFormatMarkerError,
1024 ) -> Self {
1025 Self {
1026 class: ErrorClass::Corruption,
1027 origin: ErrorOrigin::Recovery,
1028 detail: Some(ErrorDetail::Recovery(
1029 RecoveryErrorDetail::MalformedFormatMarker { reason },
1030 )),
1031 }
1032 }
1033
1034 pub(crate) fn recovery_database_format_control_unavailable() -> Self {
1036 Self::new(ErrorClass::Internal, ErrorOrigin::Recovery)
1037 }
1038
1039 pub(crate) fn recovery_pending() -> Self {
1041 Self::with_diagnostic_facts(
1042 ErrorClass::Conflict,
1043 ErrorOrigin::Recovery,
1044 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
1045 boundary: diagnostic_code::RuntimeBoundaryCode::DatabaseStartupRecoveryPending,
1046 }),
1047 Vec::new(),
1048 )
1049 }
1050
1051 pub(crate) fn startup_control_corruption() -> Self {
1053 Self::new(ErrorClass::Corruption, ErrorOrigin::Recovery)
1054 }
1055
1056 pub(crate) fn commit_control_memory_growth_failed() -> Self {
1058 Self::store_internal()
1059 }
1060
1061 pub(crate) fn recovery_effect_verification_failed() -> Self {
1063 Self::store_corruption()
1064 }
1065
1066 #[cold]
1068 #[inline(never)]
1069 pub(crate) fn index_internal() -> Self {
1070 Self::new(ErrorClass::Internal, ErrorOrigin::Index)
1071 }
1072
1073 pub(crate) fn structural_index_removal_entity_key_required() -> Self {
1075 Self::index_internal()
1076 }
1077
1078 pub(crate) fn structural_index_insertion_entity_key_required() -> Self {
1080 Self::index_internal()
1081 }
1082
1083 pub(crate) fn index_commit_op_old_entity_key_required() -> Self {
1085 Self::index_internal()
1086 }
1087
1088 pub(crate) fn index_commit_op_new_entity_key_required() -> Self {
1090 Self::index_internal()
1091 }
1092
1093 #[cfg(test)]
1095 pub(crate) fn query_internal() -> Self {
1096 Self::new(ErrorClass::Internal, ErrorOrigin::Query)
1097 }
1098
1099 #[cold]
1101 #[inline(never)]
1102 pub(crate) fn query_unsupported() -> Self {
1103 Self::new(ErrorClass::Unsupported, ErrorOrigin::Query)
1104 }
1105
1106 #[cold]
1108 #[inline(never)]
1109 pub(crate) fn query_exact_count_metadata_unavailable() -> Self {
1110 Self {
1111 class: ErrorClass::Unsupported,
1112 origin: ErrorOrigin::Query,
1113 detail: Some(ErrorDetail::Query(
1114 QueryErrorDetail::ExactCountMetadataUnavailable,
1115 )),
1116 }
1117 }
1118
1119 pub(crate) fn query_explain_output_exceeded(limit: u64, observed: u64) -> Self {
1122 Self::with_diagnostic_facts(
1123 ErrorClass::Unsupported,
1124 ErrorOrigin::Query,
1125 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
1126 boundary: diagnostic_code::RuntimeBoundaryCode::QueryExplainOutputExceeded,
1127 }),
1128 vec![
1129 (diagnostic_code::DiagnosticFactTag::Limit, limit),
1130 (diagnostic_code::DiagnosticFactTag::Actual, observed),
1131 ],
1132 )
1133 }
1134
1135 pub(crate) fn query_explain_depth_exceeded(limit: u64, observed: u64) -> Self {
1138 Self::with_diagnostic_facts(
1139 ErrorClass::Unsupported,
1140 ErrorOrigin::Query,
1141 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
1142 boundary: diagnostic_code::RuntimeBoundaryCode::QueryExplainDepthExceeded,
1143 }),
1144 vec![
1145 (diagnostic_code::DiagnosticFactTag::Limit, limit),
1146 (diagnostic_code::DiagnosticFactTag::Actual, observed),
1147 ],
1148 )
1149 }
1150
1151 #[cold]
1154 #[inline(never)]
1155 pub(crate) fn query_stale_accepted_schema_revision(
1156 expected_revision: u64,
1157 current_revision: Option<u64>,
1158 ) -> Self {
1159 let mut facts = Vec::with_capacity(1 + usize::from(current_revision.is_some()));
1160 facts.push((
1161 diagnostic_code::DiagnosticFactTag::ExpectedRevision,
1162 expected_revision,
1163 ));
1164 if let Some(current_revision) = current_revision {
1165 facts.push((
1166 diagnostic_code::DiagnosticFactTag::CurrentRevision,
1167 current_revision,
1168 ));
1169 }
1170 Self::with_diagnostic_facts(ErrorClass::Conflict, ErrorOrigin::Query, None, facts)
1171 }
1172
1173 #[cold]
1175 #[inline(never)]
1176 #[cfg(feature = "sql")]
1177 pub(crate) fn query_schema_ddl_admission(error: SchemaDdlAdmissionError) -> Self {
1178 Self {
1179 class: ErrorClass::Unsupported,
1180 origin: ErrorOrigin::Query,
1181 detail: Some(ErrorDetail::Query(QueryErrorDetail::SchemaDdlAdmission {
1182 error,
1183 })),
1184 }
1185 }
1186
1187 #[cold]
1189 #[inline(never)]
1190 pub(crate) fn query_numeric_overflow() -> Self {
1191 Self {
1192 class: ErrorClass::Unsupported,
1193 origin: ErrorOrigin::Query,
1194 detail: Some(ErrorDetail::Query(QueryErrorDetail::NumericOverflow)),
1195 }
1196 }
1197
1198 #[cold]
1201 #[inline(never)]
1202 pub(crate) fn query_numeric_not_representable() -> Self {
1203 Self {
1204 class: ErrorClass::Unsupported,
1205 origin: ErrorOrigin::Query,
1206 detail: Some(ErrorDetail::Query(
1207 QueryErrorDetail::NumericNotRepresentable,
1208 )),
1209 }
1210 }
1211
1212 #[cold]
1214 #[inline(never)]
1215 pub(crate) fn serialize_internal() -> Self {
1216 Self::new(ErrorClass::Internal, ErrorOrigin::Serialize)
1217 }
1218
1219 pub(crate) fn persisted_row_encode_internal() -> Self {
1221 Self::serialize_internal()
1222 }
1223
1224 #[cold]
1226 #[inline(never)]
1227 pub(crate) fn store_corruption() -> Self {
1228 Self::new(ErrorClass::Corruption, ErrorOrigin::Store)
1229 }
1230
1231 pub(crate) fn commit_corruption() -> Self {
1233 Self::store_corruption()
1234 }
1235
1236 pub(crate) fn commit_component_corruption() -> Self {
1238 Self::commit_corruption()
1239 }
1240
1241 pub(crate) fn commit_id_generation_failed() -> Self {
1243 Self::store_internal()
1244 }
1245
1246 pub(crate) fn commit_marker_payload_exceeds_u32_length_limit() -> Self {
1248 Self::store_unsupported()
1249 }
1250
1251 pub(crate) fn commit_component_length_invalid(actual_length: usize, limit: usize) -> Self {
1253 Self::with_diagnostic_facts(
1254 ErrorClass::Corruption,
1255 ErrorOrigin::Store,
1256 None,
1257 vec![
1258 (
1259 diagnostic_code::DiagnosticFactTag::ComponentKind,
1260 diagnostic_code::DiagnosticComponentKind::CommitDataKey.raw(),
1261 ),
1262 (
1263 diagnostic_code::DiagnosticFactTag::ActualLength,
1264 actual_length as u64,
1265 ),
1266 (diagnostic_code::DiagnosticFactTag::Limit, limit as u64),
1267 ],
1268 )
1269 }
1270
1271 pub(crate) fn commit_marker_exceeds_max_size() -> Self {
1273 Self::commit_corruption()
1274 }
1275
1276 pub(crate) fn commit_control_slot_exceeds_max_size() -> Self {
1278 Self::store_unsupported()
1279 }
1280
1281 pub(crate) fn commit_control_slot_marker_bytes_exceed_u32_length_limit() -> Self {
1283 Self::store_unsupported()
1284 }
1285
1286 #[cold]
1288 #[inline(never)]
1289 pub(crate) fn index_corruption() -> Self {
1290 Self::new(ErrorClass::Corruption, ErrorOrigin::Index)
1291 }
1292
1293 pub(crate) fn index_unique_validation_corruption() -> Self {
1295 Self::index_plan_index_corruption()
1296 }
1297
1298 pub(crate) fn structural_index_entry_corruption() -> Self {
1300 Self::index_plan_index_corruption()
1301 }
1302
1303 pub(crate) fn index_unique_validation_entity_key_required() -> Self {
1305 Self::index_invariant()
1306 }
1307
1308 pub(crate) fn index_unique_validation_row_deserialize_failed() -> Self {
1310 Self::index_plan_serialize_corruption()
1311 }
1312
1313 pub(crate) fn index_unique_validation_primary_key_decode_failed() -> Self {
1315 Self::index_plan_serialize_corruption()
1316 }
1317
1318 pub(crate) fn index_unique_validation_key_rebuild_failed() -> Self {
1320 Self::index_plan_serialize_corruption()
1321 }
1322
1323 pub(crate) fn index_unique_validation_row_required() -> Self {
1325 Self::index_plan_store_corruption()
1326 }
1327
1328 pub(crate) fn index_only_predicate_component_required() -> Self {
1330 Self::index_invariant()
1331 }
1332
1333 pub(crate) fn index_scan_continuation_anchor_within_envelope_required() -> Self {
1335 Self::index_invariant()
1336 }
1337
1338 pub(crate) fn index_scan_continuation_advancement_required() -> Self {
1340 Self::index_invariant()
1341 }
1342
1343 pub(crate) fn index_entry_decode_failed() -> Self {
1345 Self::index_corruption()
1346 }
1347
1348 pub(crate) fn serialize_corruption() -> Self {
1350 Self::new(ErrorClass::Corruption, ErrorOrigin::Serialize)
1351 }
1352
1353 pub(crate) fn persisted_row_decode_corruption() -> Self {
1355 Self::serialize_corruption()
1356 }
1357
1358 pub(crate) fn persisted_row_layout_outside_accepted_window(
1360 row_layout: u32,
1361 history_floor: u32,
1362 current_layout: u32,
1363 ) -> Self {
1364 Self::with_diagnostic_facts(
1365 ErrorClass::Corruption,
1366 ErrorOrigin::Serialize,
1367 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
1368 boundary:
1369 diagnostic_code::RuntimeBoundaryCode::PersistedRowLayoutOutsideAcceptedWindow,
1370 }),
1371 vec![
1372 (
1373 diagnostic_code::DiagnosticFactTag::RowLayout,
1374 u64::from(row_layout),
1375 ),
1376 (
1377 diagnostic_code::DiagnosticFactTag::HistoryFloor,
1378 u64::from(history_floor),
1379 ),
1380 (
1381 diagnostic_code::DiagnosticFactTag::CurrentLayout,
1382 u64::from(current_layout),
1383 ),
1384 ],
1385 )
1386 }
1387
1388 pub(crate) fn persisted_row_slot_count_mismatch(
1390 row_layout: u32,
1391 expected_slot_count: usize,
1392 actual_slot_count: usize,
1393 ) -> Self {
1394 Self::with_diagnostic_facts(
1395 ErrorClass::Corruption,
1396 ErrorOrigin::Serialize,
1397 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
1398 boundary: diagnostic_code::RuntimeBoundaryCode::PersistedRowSlotCountMismatch,
1399 }),
1400 vec![
1401 (
1402 diagnostic_code::DiagnosticFactTag::RowLayout,
1403 u64::from(row_layout),
1404 ),
1405 (
1406 diagnostic_code::DiagnosticFactTag::ExpectedSlotCount,
1407 expected_slot_count as u64,
1408 ),
1409 (
1410 diagnostic_code::DiagnosticFactTag::ActualSlotCount,
1411 actual_slot_count as u64,
1412 ),
1413 ],
1414 )
1415 }
1416
1417 pub(crate) fn persisted_row_key_mismatch() -> Self {
1419 Self::store_corruption()
1420 }
1421
1422 pub(crate) fn with_relation_identity(self, entity_tag: u64, relation_id: u32) -> Self {
1424 if self.diagnostic().error_code() != diagnostic_code::ErrorCode::RUNTIME_INTERNAL {
1425 return self;
1426 }
1427 let mut facts = vec![
1428 (diagnostic_code::DiagnosticFactTag::EntityTag, entity_tag),
1429 (
1430 diagnostic_code::DiagnosticFactTag::RelationId,
1431 u64::from(relation_id),
1432 ),
1433 ];
1434 facts.extend(self.diagnostic_facts());
1435 Self::with_diagnostic_facts(self.class, self.origin, None, facts)
1436 }
1437
1438 pub(crate) fn relation_target_primary_key_arity_mismatch(
1440 expected_arity: usize,
1441 actual_arity: usize,
1442 ) -> Self {
1443 Self::with_diagnostic_facts(
1444 ErrorClass::Internal,
1445 ErrorOrigin::Executor,
1446 None,
1447 vec![
1448 (
1449 diagnostic_code::DiagnosticFactTag::ComponentKind,
1450 diagnostic_code::DiagnosticComponentKind::RelationTargetPrimaryKey.raw(),
1451 ),
1452 (
1453 diagnostic_code::DiagnosticFactTag::ExpectedArity,
1454 expected_arity as u64,
1455 ),
1456 (
1457 diagnostic_code::DiagnosticFactTag::ActualArity,
1458 actual_arity as u64,
1459 ),
1460 ],
1461 )
1462 }
1463
1464 pub(crate) fn relation_target_entity_mismatch(expected_tag: u64, actual_tag: u64) -> Self {
1466 Self::with_diagnostic_facts(
1467 ErrorClass::Corruption,
1468 ErrorOrigin::Store,
1469 None,
1470 vec![
1471 (
1472 diagnostic_code::DiagnosticFactTag::ExpectedEntityTag,
1473 expected_tag,
1474 ),
1475 (
1476 diagnostic_code::DiagnosticFactTag::ActualEntityTag,
1477 actual_tag,
1478 ),
1479 ],
1480 )
1481 }
1482
1483 pub(crate) fn bytes_covering_component_payload_empty() -> Self {
1485 Self::index_corruption()
1486 }
1487
1488 pub(crate) fn bytes_covering_bool_payload_truncated() -> Self {
1490 Self::index_corruption()
1491 }
1492
1493 pub(crate) fn bytes_covering_component_payload_invalid_length() -> Self {
1495 Self::index_corruption()
1496 }
1497
1498 pub(crate) fn bytes_covering_bool_payload_invalid_value() -> Self {
1500 Self::index_corruption()
1501 }
1502
1503 pub(crate) fn bytes_covering_text_payload_invalid_terminator() -> Self {
1505 Self::index_corruption()
1506 }
1507
1508 pub(crate) fn bytes_covering_text_payload_trailing_bytes() -> Self {
1510 Self::index_corruption()
1511 }
1512
1513 pub(crate) fn bytes_covering_text_payload_invalid_utf8() -> Self {
1515 Self::index_corruption()
1516 }
1517
1518 pub(crate) fn bytes_covering_text_payload_invalid_escape_byte() -> Self {
1520 Self::index_corruption()
1521 }
1522
1523 pub(crate) fn bytes_covering_text_payload_missing_terminator() -> Self {
1525 Self::index_corruption()
1526 }
1527
1528 pub(crate) fn identity_corruption() -> Self {
1530 Self::new(ErrorClass::Corruption, ErrorOrigin::Identity)
1531 }
1532
1533 pub(crate) fn identity_state_corruption() -> Self {
1535 Self::identity_corruption()
1536 }
1537
1538 pub(crate) fn identity_state_conflict() -> Self {
1540 Self::new(ErrorClass::Conflict, ErrorOrigin::Identity)
1541 }
1542
1543 pub(crate) fn identity_state_capacity_exhausted() -> Self {
1545 Self::new(ErrorClass::Unsupported, ErrorOrigin::Identity)
1546 }
1547
1548 pub(crate) fn identity_exhausted() -> Self {
1550 Self::new(ErrorClass::Unsupported, ErrorOrigin::Identity)
1551 }
1552
1553 pub(crate) fn identity_candidate_count_exhausted() -> Self {
1555 Self::new(ErrorClass::Unsupported, ErrorOrigin::Identity)
1556 }
1557
1558 #[cold]
1560 #[inline(never)]
1561 pub(crate) fn store_unsupported() -> Self {
1562 Self::new(ErrorClass::Unsupported, ErrorOrigin::Store)
1563 }
1564
1565 pub(crate) fn schema_application_conflict() -> Self {
1567 Self::new(ErrorClass::Conflict, ErrorOrigin::Store)
1568 }
1569
1570 pub(crate) fn schema_migration(reason: diagnostic_code::SchemaMigrationCode) -> Self {
1572 let class = match reason.diagnostic_code() {
1573 diagnostic_code::DiagnosticCode::RuntimeConflict => ErrorClass::Conflict,
1574 diagnostic_code::DiagnosticCode::RuntimeCorruption => ErrorClass::Corruption,
1575 diagnostic_code::DiagnosticCode::RuntimeUnsupported => ErrorClass::Unsupported,
1576 _ => ErrorClass::Internal,
1577 };
1578 Self {
1579 class,
1580 origin: ErrorOrigin::Store,
1581 detail: Some(ErrorDetail::Store(StoreError::SchemaMigration { reason })),
1582 }
1583 }
1584
1585 pub(crate) fn schema_ddl_publication_race_lost() -> Self {
1587 Self {
1588 class: ErrorClass::Unsupported,
1589 origin: ErrorOrigin::Store,
1590 detail: Some(ErrorDetail::Store(StoreError::SchemaDdlPublicationRaceLost)),
1591 }
1592 }
1593
1594 #[cfg(feature = "sql")]
1596 pub(crate) fn schema_ddl_rewrite_requires_migration() -> Self {
1597 Self {
1598 class: ErrorClass::Unsupported,
1599 origin: ErrorOrigin::Store,
1600 detail: Some(ErrorDetail::Store(
1601 StoreError::SchemaDdlRewriteRequiresMigration,
1602 )),
1603 }
1604 }
1605
1606 pub(crate) fn journal_mutation_revision_exhausted() -> Self {
1608 Self {
1609 class: ErrorClass::Unsupported,
1610 origin: ErrorOrigin::Store,
1611 detail: Some(ErrorDetail::Store(
1612 StoreError::JournalMutationRevisionExhausted,
1613 )),
1614 }
1615 }
1616
1617 pub(crate) fn schema_transition_budget_exceeded(
1619 resource: SchemaTransitionBudgetResource,
1620 ) -> Self {
1621 Self {
1622 class: ErrorClass::Unsupported,
1623 origin: ErrorOrigin::Store,
1624 detail: Some(ErrorDetail::Store(
1625 StoreError::SchemaTransitionBudgetExceeded { resource },
1626 )),
1627 }
1628 }
1629
1630 pub(crate) fn index_unsupported() -> Self {
1632 Self::new(ErrorClass::Unsupported, ErrorOrigin::Index)
1633 }
1634
1635 pub(crate) fn index_component_exceeds_max_size_at(
1637 entity_tag: u64,
1638 physical_generation: u64,
1639 component_index: usize,
1640 actual_length: usize,
1641 limit: usize,
1642 ) -> Self {
1643 Self::with_diagnostic_facts(
1644 ErrorClass::Unsupported,
1645 ErrorOrigin::Index,
1646 None,
1647 vec![
1648 (diagnostic_code::DiagnosticFactTag::EntityTag, entity_tag),
1649 (
1650 diagnostic_code::DiagnosticFactTag::PhysicalGeneration,
1651 physical_generation,
1652 ),
1653 (
1654 diagnostic_code::DiagnosticFactTag::ComponentIndex,
1655 component_index as u64,
1656 ),
1657 (
1658 diagnostic_code::DiagnosticFactTag::ComponentKind,
1659 diagnostic_code::DiagnosticComponentKind::IndexKeyComponent.raw(),
1660 ),
1661 (
1662 diagnostic_code::DiagnosticFactTag::ActualLength,
1663 actual_length as u64,
1664 ),
1665 (diagnostic_code::DiagnosticFactTag::Limit, limit as u64),
1666 ],
1667 )
1668 }
1669
1670 pub(crate) fn index_component_exceeds_max_size() -> Self {
1673 Self::index_unsupported()
1674 }
1675
1676 pub(crate) fn serialize_unsupported() -> Self {
1678 Self::new(ErrorClass::Unsupported, ErrorOrigin::Serialize)
1679 }
1680
1681 pub(crate) fn cursor_invalid_continuation() -> Self {
1683 Self::new(ErrorClass::Unsupported, ErrorOrigin::Cursor)
1684 }
1685
1686 pub(crate) fn serialize_incompatible_persisted_format() -> Self {
1688 Self::new(
1689 ErrorClass::IncompatiblePersistedFormat,
1690 ErrorOrigin::Serialize,
1691 )
1692 }
1693
1694 #[cfg(feature = "sql")]
1697 pub(crate) fn query_unsupported_sql_feature(feature: diagnostic_code::SqlFeatureCode) -> Self {
1698 Self {
1699 class: ErrorClass::Unsupported,
1700 origin: ErrorOrigin::Query,
1701 detail: Some(ErrorDetail::Query(
1702 QueryErrorDetail::UnsupportedSqlFeature { feature },
1703 )),
1704 }
1705 }
1706
1707 #[cfg(feature = "sql")]
1710 pub(crate) fn query_sql_lowering(reason: diagnostic_code::SqlLoweringCode) -> Self {
1711 Self {
1712 class: ErrorClass::Unsupported,
1713 origin: ErrorOrigin::Query,
1714 detail: Some(ErrorDetail::Query(QueryErrorDetail::SqlLowering { reason })),
1715 }
1716 }
1717
1718 #[cfg(feature = "sql")]
1720 pub(crate) fn query_sql_lowering_with_facts(
1721 reason: diagnostic_code::SqlLoweringCode,
1722 facts: Vec<(diagnostic_code::DiagnosticFactTag, u64)>,
1723 ) -> Self {
1724 Self::with_diagnostic_facts(
1725 ErrorClass::Unsupported,
1726 ErrorOrigin::Query,
1727 Some(diagnostic_code::DiagnosticDetail::SqlLowering { reason }),
1728 facts,
1729 )
1730 }
1731
1732 pub(crate) fn query_unsupported_projection(
1735 reason: diagnostic_code::QueryProjectionCode,
1736 ) -> Self {
1737 Self {
1738 class: ErrorClass::Unsupported,
1739 origin: ErrorOrigin::Query,
1740 detail: Some(ErrorDetail::Query(
1741 QueryErrorDetail::UnsupportedProjection { reason },
1742 )),
1743 }
1744 }
1745
1746 #[cfg(feature = "sql")]
1749 pub(crate) fn query_sql_surface_mismatch(
1750 mismatch: diagnostic_code::SqlSurfaceMismatchCode,
1751 ) -> Self {
1752 Self {
1753 class: ErrorClass::Unsupported,
1754 origin: ErrorOrigin::Query,
1755 detail: Some(ErrorDetail::Query(QueryErrorDetail::SqlSurfaceMismatch {
1756 mismatch,
1757 })),
1758 }
1759 }
1760
1761 pub(crate) fn query_sql_write_boundary(
1763 boundary: diagnostic_code::SqlWriteBoundaryCode,
1764 ) -> Self {
1765 Self {
1766 class: ErrorClass::Unsupported,
1767 origin: ErrorOrigin::Query,
1768 detail: Some(ErrorDetail::Query(QueryErrorDetail::SqlWriteBoundary {
1769 boundary,
1770 })),
1771 }
1772 }
1773
1774 pub(crate) fn query_sql_write_boundary_with_facts(
1776 boundary: diagnostic_code::SqlWriteBoundaryCode,
1777 facts: Vec<(diagnostic_code::DiagnosticFactTag, u64)>,
1778 ) -> Self {
1779 Self::with_diagnostic_facts(
1780 ErrorClass::Unsupported,
1781 ErrorOrigin::Query,
1782 Some(diagnostic_code::DiagnosticDetail::SqlWriteBoundary { boundary }),
1783 facts,
1784 )
1785 }
1786
1787 pub fn store_not_found(_key: impl Sized) -> Self {
1788 Self {
1789 class: ErrorClass::NotFound,
1790 origin: ErrorOrigin::Store,
1791 detail: Some(ErrorDetail::Store(StoreError::NotFound)),
1792 }
1793 }
1794
1795 pub fn unsupported_entity_path(_path: impl Sized) -> Self {
1797 Self::store_unsupported()
1798 }
1799
1800 #[cold]
1802 #[inline(never)]
1803 pub(crate) fn index_plan_corruption(origin: ErrorOrigin) -> Self {
1804 Self::new(ErrorClass::Corruption, origin)
1805 }
1806
1807 #[cold]
1809 #[inline(never)]
1810 pub(crate) fn index_plan_index_corruption() -> Self {
1811 Self::index_plan_corruption(ErrorOrigin::Index)
1812 }
1813
1814 #[cold]
1816 #[inline(never)]
1817 pub(crate) fn index_plan_store_corruption() -> Self {
1818 Self::index_plan_corruption(ErrorOrigin::Store)
1819 }
1820
1821 #[cold]
1823 #[inline(never)]
1824 pub(crate) fn index_plan_serialize_corruption() -> Self {
1825 Self::index_plan_corruption(ErrorOrigin::Serialize)
1826 }
1827
1828 #[cfg(test)]
1830 pub(crate) fn index_plan_invariant(origin: ErrorOrigin) -> Self {
1831 Self::new(ErrorClass::InvariantViolation, origin)
1832 }
1833
1834 #[cfg(test)]
1836 pub(crate) fn index_plan_store_invariant() -> Self {
1837 Self::index_plan_invariant(ErrorOrigin::Store)
1838 }
1839
1840 pub(crate) fn index_conflict() -> Self {
1846 Self::new(ErrorClass::Conflict, ErrorOrigin::Index)
1847 }
1848}
1849
1850impl From<diagnostic_code::QueryReadAdmissionCode> for InternalError {
1851 fn from(reason: diagnostic_code::QueryReadAdmissionCode) -> Self {
1852 Self {
1853 class: ErrorClass::Unsupported,
1854 origin: ErrorOrigin::Query,
1855 detail: Some(ErrorDetail::Query(QueryErrorDetail::QueryReadAdmission {
1856 reason,
1857 })),
1858 }
1859 }
1860}
1861
1862impl fmt::Debug for InternalError {
1863 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1864 fmt_compact_diagnostic(
1865 f,
1866 self.diagnostic_code(),
1867 self.detail
1868 .as_ref()
1869 .and_then(ErrorDetail::diagnostic_detail),
1870 )
1871 }
1872}
1873
1874impl fmt::Display for InternalError {
1875 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1876 f.write_str(self.message())
1877 }
1878}
1879
1880impl std::error::Error for InternalError {}
1881
1882#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq)]
1891pub enum ConstraintValuePathComponent {
1892 RootField { field_id: u32 },
1894
1895 RecordMember {
1897 composite_type_id: u32,
1898 member_id: u32,
1899 },
1900
1901 TupleElement {
1903 composite_type_id: u32,
1904 ordinal: u32,
1905 },
1906
1907 Newtype { composite_type_id: u32 },
1909
1910 EnumVariant { enum_type_id: u32, variant_id: u32 },
1912
1913 ListElement { index: u32 },
1915
1916 SetElement { index: u32 },
1918
1919 MapEntryKey { index: u32 },
1921
1922 MapEntryValue { index: u32 },
1924}
1925
1926impl fmt::Display for ConstraintValuePathComponent {
1927 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1928 match self {
1929 Self::RootField { field_id } => write!(f, "field#{field_id}"),
1930 Self::RecordMember {
1931 composite_type_id,
1932 member_id,
1933 } => write!(f, "record#{composite_type_id}.member#{member_id}"),
1934 Self::TupleElement {
1935 composite_type_id,
1936 ordinal,
1937 } => write!(f, "tuple#{composite_type_id}[{ordinal}]"),
1938 Self::Newtype { composite_type_id } => write!(f, "newtype#{composite_type_id}"),
1939 Self::EnumVariant {
1940 enum_type_id,
1941 variant_id,
1942 } => write!(f, "enum#{enum_type_id}.variant#{variant_id}"),
1943 Self::ListElement { index } => write!(f, "list[{index}]"),
1944 Self::SetElement { index } => write!(f, "set[{index}]"),
1945 Self::MapEntryKey { index } => write!(f, "map[{index}].key"),
1946 Self::MapEntryValue { index } => write!(f, "map[{index}].value"),
1947 }
1948 }
1949}
1950
1951#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
1958pub struct ConstraintValuePath {
1959 components: Vec<ConstraintValuePathComponent>,
1960}
1961
1962impl ConstraintValuePath {
1963 #[must_use]
1965 pub(crate) const fn new(components: Vec<ConstraintValuePathComponent>) -> Self {
1966 Self { components }
1967 }
1968
1969 #[must_use]
1971 pub const fn components(&self) -> &[ConstraintValuePathComponent] {
1972 self.components.as_slice()
1973 }
1974}
1975
1976impl fmt::Display for ConstraintValuePath {
1977 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1978 for (ordinal, component) in self.components.iter().enumerate() {
1979 if ordinal != 0 {
1980 f.write_str("/")?;
1981 }
1982 component.fmt(f)?;
1983 }
1984 Ok(())
1985 }
1986}
1987
1988#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
1997pub struct ConstraintValidationFindingOutput {
1998 accepted_schema_fingerprint: [u8; 16],
1999 entity_tag: u64,
2000 constraint_id: u32,
2001 primary_key: Vec<u8>,
2002 field_ids: Vec<u32>,
2003 value_path: Option<ConstraintValuePath>,
2004 error_code: u16,
2005}
2006
2007impl ConstraintValidationFindingOutput {
2008 #[must_use]
2010 pub(crate) const fn new(
2011 accepted_schema_fingerprint: [u8; 16],
2012 entity_tag: u64,
2013 constraint_id: u32,
2014 primary_key: Vec<u8>,
2015 field_ids: Vec<u32>,
2016 value_path: Option<ConstraintValuePath>,
2017 error_code: u16,
2018 ) -> Self {
2019 Self {
2020 accepted_schema_fingerprint,
2021 entity_tag,
2022 constraint_id,
2023 primary_key,
2024 field_ids,
2025 value_path,
2026 error_code,
2027 }
2028 }
2029
2030 #[must_use]
2032 pub const fn accepted_schema_fingerprint(&self) -> [u8; 16] {
2033 self.accepted_schema_fingerprint
2034 }
2035
2036 #[must_use]
2038 pub const fn entity_tag(&self) -> u64 {
2039 self.entity_tag
2040 }
2041
2042 #[must_use]
2044 pub const fn constraint_id(&self) -> u32 {
2045 self.constraint_id
2046 }
2047
2048 #[must_use]
2050 pub const fn primary_key(&self) -> &[u8] {
2051 self.primary_key.as_slice()
2052 }
2053
2054 #[must_use]
2056 pub const fn field_ids(&self) -> &[u32] {
2057 self.field_ids.as_slice()
2058 }
2059
2060 #[must_use]
2062 pub const fn value_path(&self) -> Option<&ConstraintValuePath> {
2063 self.value_path.as_ref()
2064 }
2065
2066 #[must_use]
2068 pub const fn error_code(&self) -> diagnostic_code::ErrorCode {
2069 diagnostic_code::ErrorCode::from_raw(self.error_code)
2070 }
2071
2072 #[must_use]
2074 pub const fn error_class(&self) -> diagnostic_code::ErrorClass {
2075 self.error_code().class()
2076 }
2077}
2078
2079#[derive(Clone)]
2081pub(crate) struct AcceptedConstraintFactContext {
2082 fingerprint_method: u8,
2083 accepted_schema_fingerprint: [u8; 16],
2084 entity_tag: u64,
2085 constraint_id: u32,
2086 constraint_kind: diagnostic_code::DiagnosticConstraintKind,
2087 mutation: Option<MutationDiagnosticContext>,
2088 value_path: Option<ConstraintValuePath>,
2089}
2090
2091impl AcceptedConstraintFactContext {
2092 #[must_use]
2093 pub(crate) fn write_admission(
2094 fingerprint_method: u8,
2095 accepted_schema_fingerprint: [u8; 16],
2096 entity_tag: u64,
2097 constraint_id: u32,
2098 constraint_kind: diagnostic_code::DiagnosticConstraintKind,
2099 mutation: Option<MutationDiagnosticContext>,
2100 value_path: Option<ConstraintValuePath>,
2101 ) -> Self {
2102 debug_assert!(mutation.is_none_or(|context| context.entity_tag() == entity_tag));
2103 Self {
2104 fingerprint_method,
2105 accepted_schema_fingerprint,
2106 entity_tag,
2107 constraint_id,
2108 constraint_kind,
2109 mutation,
2110 value_path,
2111 }
2112 }
2113
2114 fn facts(self) -> Vec<(diagnostic_code::DiagnosticFactTag, u64)> {
2115 let path_len = self
2116 .value_path
2117 .as_ref()
2118 .map_or(0, |path| path.components().len());
2119 let mutation_fact_count = self.mutation.map_or(0, |mutation| {
2120 1 + usize::from(mutation.batch_position.is_some())
2121 });
2122 let mut facts = Vec::with_capacity(7 + mutation_fact_count + path_len);
2123 append_accepted_schema_facts(
2124 &mut facts,
2125 self.fingerprint_method,
2126 self.accepted_schema_fingerprint,
2127 );
2128 facts.push((
2129 diagnostic_code::DiagnosticFactTag::EntityTag,
2130 self.entity_tag,
2131 ));
2132 facts.push((
2133 diagnostic_code::DiagnosticFactTag::ConstraintId,
2134 u64::from(self.constraint_id),
2135 ));
2136 facts.push((
2137 diagnostic_code::DiagnosticFactTag::ConstraintKind,
2138 self.constraint_kind.raw(),
2139 ));
2140 facts.push((
2141 diagnostic_code::DiagnosticFactTag::ConstraintContext,
2142 diagnostic_code::DiagnosticConstraintContext::WriteAdmission.raw(),
2143 ));
2144 if let Some(mutation) = self.mutation {
2145 mutation.append_operation_facts(&mut facts);
2146 }
2147 if let Some(path) = self.value_path {
2148 for component in path.components {
2149 facts.push(constraint_value_path_fact(component));
2150 }
2151 }
2152 debug_assert!(facts.len() <= diagnostic_code::MAX_PUBLIC_DIAGNOSTIC_FACTS);
2153 facts
2154 }
2155}
2156
2157fn append_accepted_schema_facts(
2159 facts: &mut Vec<(diagnostic_code::DiagnosticFactTag, u64)>,
2160 method: u8,
2161 fingerprint: [u8; 16],
2162) {
2163 facts.extend([
2164 (
2165 diagnostic_code::DiagnosticFactTag::AcceptedSchemaFingerprintMethod,
2166 u64::from(method),
2167 ),
2168 (
2169 diagnostic_code::DiagnosticFactTag::AcceptedSchemaFingerprintHigh,
2170 u64::from_be_bytes([
2171 fingerprint[0],
2172 fingerprint[1],
2173 fingerprint[2],
2174 fingerprint[3],
2175 fingerprint[4],
2176 fingerprint[5],
2177 fingerprint[6],
2178 fingerprint[7],
2179 ]),
2180 ),
2181 (
2182 diagnostic_code::DiagnosticFactTag::AcceptedSchemaFingerprintLow,
2183 u64::from_be_bytes([
2184 fingerprint[8],
2185 fingerprint[9],
2186 fingerprint[10],
2187 fingerprint[11],
2188 fingerprint[12],
2189 fingerprint[13],
2190 fingerprint[14],
2191 fingerprint[15],
2192 ]),
2193 ),
2194 ]);
2195}
2196
2197fn constraint_value_path_fact(
2198 component: ConstraintValuePathComponent,
2199) -> (diagnostic_code::DiagnosticFactTag, u64) {
2200 use diagnostic_code::DiagnosticFactTag;
2201 match component {
2202 ConstraintValuePathComponent::RootField { field_id } => {
2203 (DiagnosticFactTag::RootField, u64::from(field_id))
2204 }
2205 ConstraintValuePathComponent::RecordMember {
2206 composite_type_id,
2207 member_id,
2208 } => (
2209 DiagnosticFactTag::RecordMember,
2210 diagnostic_code::pack_u32_pair(composite_type_id, member_id),
2211 ),
2212 ConstraintValuePathComponent::TupleElement {
2213 composite_type_id,
2214 ordinal,
2215 } => (
2216 DiagnosticFactTag::TupleElement,
2217 diagnostic_code::pack_u32_pair(composite_type_id, ordinal),
2218 ),
2219 ConstraintValuePathComponent::Newtype { composite_type_id } => {
2220 (DiagnosticFactTag::Newtype, u64::from(composite_type_id))
2221 }
2222 ConstraintValuePathComponent::EnumVariant {
2223 enum_type_id,
2224 variant_id,
2225 } => (
2226 DiagnosticFactTag::EnumVariant,
2227 diagnostic_code::pack_u32_pair(enum_type_id, variant_id),
2228 ),
2229 ConstraintValuePathComponent::ListElement { index } => {
2230 (DiagnosticFactTag::ListElement, u64::from(index))
2231 }
2232 ConstraintValuePathComponent::SetElement { index } => {
2233 (DiagnosticFactTag::SetElement, u64::from(index))
2234 }
2235 ConstraintValuePathComponent::MapEntryKey { index } => {
2236 (DiagnosticFactTag::MapEntryKey, u64::from(index))
2237 }
2238 ConstraintValuePathComponent::MapEntryValue { index } => {
2239 (DiagnosticFactTag::MapEntryValue, u64::from(index))
2240 }
2241 }
2242}
2243
2244pub enum ErrorDetail {
2252 DiagnosticFacts(Box<DiagnosticFactDetail>),
2254 Executor(ExecutorErrorDetail),
2256 Store(StoreError),
2257 Query(QueryErrorDetail),
2258 Recovery(RecoveryErrorDetail),
2259 }
2262
2263pub enum ExecutorErrorDetail {
2265 MutationRequiredFieldMissing,
2267 MutationManagedTimestampRegression,
2269 MutationDatabaseOwnedFieldExplicit,
2271 MutationBatchEmpty,
2273 MutationBatchTooManyItems,
2275 MutationBatchStagedBytesExceeded,
2277 MutationBatchResultBytesExceeded,
2279 MutationBatchStoreMismatch,
2281 MutationBatchTooManyEntities,
2283 MutationBatchDuplicateKey,
2285 AcceptedRowConstraintProgramCorrupt,
2287}
2288
2289pub enum RecoveryErrorDetail {
2296 UnsupportedFormatVersion { found: Option<u16>, required: u16 },
2297
2298 MalformedFormatMarker { reason: RecoveryFormatMarkerError },
2299}
2300
2301#[derive(Clone, Copy, Eq, PartialEq)]
2303pub enum RecoveryFormatMarkerError {
2304 Magic,
2305 Checksum,
2306 State,
2307}
2308
2309impl RecoveryFormatMarkerError {
2310 const fn diagnostic_decode_reason(self) -> diagnostic_code::DiagnosticDecodeReason {
2311 match self {
2312 Self::Magic => diagnostic_code::DiagnosticDecodeReason::RecoveryMarkerMagic,
2313 Self::Checksum => diagnostic_code::DiagnosticDecodeReason::RecoveryMarkerChecksum,
2314 Self::State => diagnostic_code::DiagnosticDecodeReason::RecoveryMarkerState,
2315 }
2316 }
2317}
2318
2319pub enum StoreError {
2327 NotFound,
2328
2329 Corrupt,
2330
2331 InvariantViolation,
2332
2333 SchemaDdlPublicationRaceLost,
2334
2335 SchemaDdlRewriteRequiresMigration,
2336
2337 SchemaMigration {
2338 reason: diagnostic_code::SchemaMigrationCode,
2339 },
2340
2341 SchemaRowLayoutVersionExhausted,
2342
2343 JournalMutationRevisionExhausted,
2344
2345 SchemaTransitionBudgetExceeded {
2346 resource: SchemaTransitionBudgetResource,
2347 },
2348
2349 SchemaGeneratedFieldAfterDdlField,
2351
2352 SchemaGeneratedConstraintActivationStale,
2354}
2355
2356pub enum QueryErrorDetail {
2363 ExactCountMetadataUnavailable,
2365
2366 NumericOverflow,
2367
2368 NumericNotRepresentable,
2369
2370 UnsupportedSqlFeature {
2371 feature: diagnostic_code::SqlFeatureCode,
2372 },
2373
2374 SqlLowering {
2375 reason: diagnostic_code::SqlLoweringCode,
2376 },
2377
2378 UnsupportedProjection {
2379 reason: diagnostic_code::QueryProjectionCode,
2380 },
2381
2382 UnknownAggregateTargetField,
2383
2384 QueryReadAdmission {
2385 reason: diagnostic_code::QueryReadAdmissionCode,
2386 },
2387
2388 SqlSurfaceMismatch {
2389 mismatch: diagnostic_code::SqlSurfaceMismatchCode,
2390 },
2391
2392 SqlWriteBoundary {
2393 boundary: diagnostic_code::SqlWriteBoundaryCode,
2394 },
2395
2396 SchemaDdlAdmission {
2397 error: SchemaDdlAdmissionError,
2398 },
2399
2400 StaleSchemaRevision,
2401}
2402
2403impl fmt::Display for QueryErrorDetail {
2404 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2405 f.write_str(COMPACT_QUERY_DIAGNOSTIC_MESSAGE)
2406 }
2407}
2408
2409impl std::error::Error for QueryErrorDetail {}
2410
2411#[derive(Clone, Copy, Debug, Eq, PartialEq)]
2419pub enum SchemaTransitionBudgetResource {
2420 DeletionKeys,
2422 ProjectionEntries,
2424 ProjectionWorkUnits,
2426 SourceRows,
2428 SourceRowBytes,
2430 StagedRawBytes,
2432}
2433
2434#[derive(Clone, Copy, Eq, PartialEq)]
2443pub enum SchemaDdlAdmissionError {
2444 MissingExpectedSchemaVersion,
2445
2446 MissingNextSchemaVersion,
2447
2448 StaleExpectedSchemaVersion,
2449
2450 InvalidExpectedSchemaVersion,
2451
2452 InvalidNextSchemaVersion,
2453
2454 AcceptedSchemaChangeWithoutVersionBump,
2455
2456 EmptyVersionBump,
2457
2458 VersionGap,
2459
2460 VersionRollback,
2461
2462 FingerprintMethodMismatch,
2463
2464 UnsupportedTransitionClass,
2465
2466 PhysicalRunnerMissing,
2467
2468 ValidationFailed,
2469
2470 PublicationRaceLost,
2471
2472 InvalidAddColumnDefault,
2473
2474 InvalidAlterColumnDefault,
2475
2476 RowLayoutVersionExhausted,
2477
2478 GeneratedIndexDropRejected,
2479
2480 SchemaRewriteRequiresMigration,
2481
2482 SchemaTransitionBudgetExceeded {
2483 resource: SchemaTransitionBudgetResource,
2484 },
2485
2486 GeneratedFieldDefaultChangeRejected,
2487
2488 GeneratedFieldNullabilityChangeRejected,
2489}
2490
2491impl fmt::Display for SchemaDdlAdmissionError {
2492 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2493 f.write_str(COMPACT_QUERY_DIAGNOSTIC_MESSAGE)
2494 }
2495}
2496
2497impl std::error::Error for SchemaDdlAdmissionError {}
2498
2499impl fmt::Debug for ErrorDetail {
2500 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2501 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2502 }
2503}
2504
2505impl fmt::Debug for ExecutorErrorDetail {
2506 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2507 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2508 }
2509}
2510
2511impl fmt::Debug for StoreError {
2512 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2513 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2514 }
2515}
2516
2517impl fmt::Debug for QueryErrorDetail {
2518 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2519 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2520 }
2521}
2522
2523impl fmt::Debug for RecoveryErrorDetail {
2524 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2525 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2526 }
2527}
2528
2529impl fmt::Debug for RecoveryFormatMarkerError {
2530 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2531 fmt_compact_diagnostic(
2532 f,
2533 diagnostic_code::DiagnosticCode::RuntimeCorruption,
2534 Some(diagnostic_code::DiagnosticDetail::RuntimeKind {
2535 kind: diagnostic_code::RuntimeErrorKind::Corruption,
2536 }),
2537 )
2538 }
2539}
2540
2541impl fmt::Debug for SchemaDdlAdmissionError {
2542 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2543 fmt_compact_diagnostic(
2544 f,
2545 diagnostic_code::DiagnosticCode::SchemaDdlAdmission,
2546 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2547 reason: self.diagnostic_code(),
2548 }),
2549 )
2550 }
2551}
2552
2553fn fmt_compact_diagnostic(
2554 f: &mut fmt::Formatter<'_>,
2555 code: diagnostic_code::DiagnosticCode,
2556 detail: Option<diagnostic_code::DiagnosticDetail>,
2557) -> fmt::Result {
2558 write!(
2559 f,
2560 "{}",
2561 diagnostic_code::ErrorCode::from_parts(code, detail).raw()
2562 )
2563}
2564
2565impl ErrorDetail {
2566 #[must_use]
2568 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2569 match self {
2570 Self::DiagnosticFacts(detail) => detail.diagnostic.code(),
2571 Self::Executor(error) => error.diagnostic_code(),
2572 Self::Store(error) => error.diagnostic_code(),
2573 Self::Query(error) => error.diagnostic_code(),
2574 Self::Recovery(error) => error.diagnostic_code(),
2575 }
2576 }
2577
2578 #[must_use]
2580 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2581 match self {
2582 Self::DiagnosticFacts(detail) => detail.diagnostic.detail().copied(),
2583 Self::Executor(error) => error.diagnostic_detail(),
2584 Self::Store(error) => error.diagnostic_detail(),
2585 Self::Query(error) => error.diagnostic_detail(),
2586 Self::Recovery(error) => error.diagnostic_detail(),
2587 }
2588 }
2589
2590 #[must_use]
2592 #[cold]
2593 #[inline(never)]
2594 pub fn diagnostic_facts(&self) -> Vec<(diagnostic_code::DiagnosticFactTag, u64)> {
2595 match self {
2596 Self::DiagnosticFacts(detail) => detail.facts.clone(),
2597 Self::Executor(error) => error.diagnostic_facts(),
2598 Self::Query(error) => error.diagnostic_facts(),
2599 Self::Recovery(error) => error.diagnostic_facts(),
2600 Self::Store(_) => Vec::new(),
2601 }
2602 }
2603}
2604
2605impl ExecutorErrorDetail {
2606 #[must_use]
2608 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2609 match self {
2610 Self::MutationRequiredFieldMissing
2611 | Self::MutationDatabaseOwnedFieldExplicit
2612 | Self::MutationBatchEmpty
2613 | Self::MutationBatchTooManyItems
2614 | Self::MutationBatchTooManyEntities
2615 | Self::MutationBatchStagedBytesExceeded
2616 | Self::MutationBatchResultBytesExceeded => {
2617 diagnostic_code::DiagnosticCode::RuntimeUnsupported
2618 }
2619 Self::MutationBatchStoreMismatch | Self::MutationBatchDuplicateKey => {
2620 diagnostic_code::DiagnosticCode::RuntimeConflict
2621 }
2622 Self::MutationManagedTimestampRegression => {
2623 diagnostic_code::DiagnosticCode::RuntimeInvariantViolation
2624 }
2625 Self::AcceptedRowConstraintProgramCorrupt => {
2626 diagnostic_code::DiagnosticCode::RuntimeCorruption
2627 }
2628 }
2629 }
2630
2631 #[must_use]
2633 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2634 match self {
2635 Self::MutationRequiredFieldMissing => {
2636 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2637 boundary: diagnostic_code::RuntimeBoundaryCode::MutationRequiredFieldMissing,
2638 })
2639 }
2640 Self::MutationDatabaseOwnedFieldExplicit => {
2641 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2642 boundary:
2643 diagnostic_code::RuntimeBoundaryCode::MutationDatabaseOwnedFieldExplicit,
2644 })
2645 }
2646 Self::MutationBatchEmpty => Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2647 boundary: diagnostic_code::RuntimeBoundaryCode::MutationBatchEmpty,
2648 }),
2649 Self::MutationBatchTooManyItems => {
2650 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2651 boundary: diagnostic_code::RuntimeBoundaryCode::MutationBatchTooManyItems,
2652 })
2653 }
2654 Self::MutationBatchStagedBytesExceeded => {
2655 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2656 boundary:
2657 diagnostic_code::RuntimeBoundaryCode::MutationBatchStagedBytesExceeded,
2658 })
2659 }
2660 Self::MutationBatchResultBytesExceeded => {
2661 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2662 boundary:
2663 diagnostic_code::RuntimeBoundaryCode::MutationBatchResultBytesExceeded,
2664 })
2665 }
2666 Self::MutationBatchStoreMismatch => {
2667 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2668 boundary: diagnostic_code::RuntimeBoundaryCode::MutationBatchStoreMismatch,
2669 })
2670 }
2671 Self::MutationBatchTooManyEntities => {
2672 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2673 boundary: diagnostic_code::RuntimeBoundaryCode::MutationBatchTooManyEntities,
2674 })
2675 }
2676 Self::MutationBatchDuplicateKey => {
2677 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2678 boundary: diagnostic_code::RuntimeBoundaryCode::MutationBatchDuplicateKey,
2679 })
2680 }
2681 Self::MutationManagedTimestampRegression => {
2682 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2683 boundary:
2684 diagnostic_code::RuntimeBoundaryCode::MutationManagedTimestampRegression,
2685 })
2686 }
2687 Self::AcceptedRowConstraintProgramCorrupt => {
2688 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2689 boundary:
2690 diagnostic_code::RuntimeBoundaryCode::AcceptedRowConstraintProgramCorrupt,
2691 })
2692 }
2693 }
2694 }
2695
2696 #[must_use]
2698 #[cold]
2699 #[inline(never)]
2700 pub const fn diagnostic_facts(&self) -> Vec<(diagnostic_code::DiagnosticFactTag, u64)> {
2701 Vec::new()
2702 }
2703}
2704
2705impl RecoveryErrorDetail {
2706 #[must_use]
2708 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2709 match self {
2710 Self::UnsupportedFormatVersion { .. } => {
2711 diagnostic_code::DiagnosticCode::RuntimeIncompatiblePersistedFormat
2712 }
2713 Self::MalformedFormatMarker { .. } => {
2714 diagnostic_code::DiagnosticCode::RuntimeCorruption
2715 }
2716 }
2717 }
2718
2719 #[must_use]
2721 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2722 let kind = match self {
2723 Self::UnsupportedFormatVersion { .. } => {
2724 diagnostic_code::RuntimeErrorKind::IncompatiblePersistedFormat
2725 }
2726 Self::MalformedFormatMarker { .. } => diagnostic_code::RuntimeErrorKind::Corruption,
2727 };
2728
2729 Some(diagnostic_code::DiagnosticDetail::RuntimeKind { kind })
2730 }
2731
2732 #[must_use]
2734 pub fn diagnostic_facts(&self) -> Vec<(diagnostic_code::DiagnosticFactTag, u64)> {
2735 match self {
2736 Self::UnsupportedFormatVersion { found, required } => {
2737 let mut facts = Vec::with_capacity(usize::from(found.is_some()) + 1);
2738 facts.push((
2739 diagnostic_code::DiagnosticFactTag::ExpectedVersion,
2740 u64::from(*required),
2741 ));
2742 if let Some(found) = found {
2743 facts.push((
2744 diagnostic_code::DiagnosticFactTag::ActualVersion,
2745 u64::from(*found),
2746 ));
2747 }
2748 facts
2749 }
2750 Self::MalformedFormatMarker { reason } => vec![(
2751 diagnostic_code::DiagnosticFactTag::DecodeReason,
2752 reason.diagnostic_decode_reason().raw(),
2753 )],
2754 }
2755 }
2756}
2757
2758impl StoreError {
2759 #[must_use]
2761 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2762 match self {
2763 Self::NotFound => diagnostic_code::DiagnosticCode::StoreNotFound,
2764 Self::Corrupt => diagnostic_code::DiagnosticCode::StoreCorruption,
2765 Self::InvariantViolation => diagnostic_code::DiagnosticCode::StoreInvariantViolation,
2766 Self::SchemaDdlPublicationRaceLost
2767 | Self::SchemaDdlRewriteRequiresMigration
2768 | Self::SchemaRowLayoutVersionExhausted
2769 | Self::SchemaTransitionBudgetExceeded { .. } => {
2770 diagnostic_code::DiagnosticCode::SchemaDdlAdmission
2771 }
2772 Self::JournalMutationRevisionExhausted | Self::SchemaGeneratedFieldAfterDdlField => {
2773 diagnostic_code::DiagnosticCode::RuntimeUnsupported
2774 }
2775 Self::SchemaGeneratedConstraintActivationStale => {
2776 diagnostic_code::DiagnosticCode::RuntimeConflict
2777 }
2778 Self::SchemaMigration { reason } => reason.diagnostic_code(),
2779 }
2780 }
2781
2782 #[must_use]
2784 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2785 match self {
2786 Self::SchemaDdlPublicationRaceLost => {
2787 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2788 reason: diagnostic_code::SchemaDdlAdmissionCode::PublicationRaceLost,
2789 })
2790 }
2791 Self::SchemaDdlRewriteRequiresMigration => {
2792 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2793 reason: diagnostic_code::SchemaDdlAdmissionCode::SchemaRewriteRequiresMigration,
2794 })
2795 }
2796 Self::SchemaMigration { reason } => {
2797 Some(diagnostic_code::DiagnosticDetail::SchemaMigration { reason: *reason })
2798 }
2799 Self::SchemaRowLayoutVersionExhausted => {
2800 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2801 reason: diagnostic_code::SchemaDdlAdmissionCode::RowLayoutVersionExhausted,
2802 })
2803 }
2804 Self::JournalMutationRevisionExhausted => {
2805 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2806 boundary:
2807 diagnostic_code::RuntimeBoundaryCode::JournalMutationRevisionExhausted,
2808 })
2809 }
2810 Self::SchemaTransitionBudgetExceeded { .. } => {
2811 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2812 reason: diagnostic_code::SchemaDdlAdmissionCode::SchemaTransitionBudgetExceeded,
2813 })
2814 }
2815 Self::SchemaGeneratedFieldAfterDdlField => {
2816 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2817 boundary: diagnostic_code::RuntimeBoundaryCode::GeneratedFieldAfterDdlField,
2818 })
2819 }
2820 Self::SchemaGeneratedConstraintActivationStale => {
2821 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2822 boundary:
2823 diagnostic_code::RuntimeBoundaryCode::GeneratedConstraintActivationStale,
2824 })
2825 }
2826 Self::NotFound | Self::Corrupt | Self::InvariantViolation => None,
2827 }
2828 }
2829}
2830
2831impl QueryErrorDetail {
2832 #[must_use]
2834 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2835 match self {
2836 Self::ExactCountMetadataUnavailable => {
2837 diagnostic_code::DiagnosticCode::QueryExactCountMetadataUnavailable
2838 }
2839 Self::NumericOverflow => diagnostic_code::DiagnosticCode::QueryNumericOverflow,
2840 Self::NumericNotRepresentable => {
2841 diagnostic_code::DiagnosticCode::QueryNumericNotRepresentable
2842 }
2843 Self::UnsupportedSqlFeature { .. } => {
2844 diagnostic_code::DiagnosticCode::QueryUnsupportedSqlFeature
2845 }
2846 Self::SqlLowering { .. } => diagnostic_code::DiagnosticCode::QueryUnsupportedSqlFeature,
2847 Self::UnsupportedProjection { .. } => {
2848 diagnostic_code::DiagnosticCode::QueryUnsupportedProjection
2849 }
2850 Self::UnknownAggregateTargetField => {
2851 diagnostic_code::DiagnosticCode::QueryUnknownAggregateTargetField
2852 }
2853 Self::QueryReadAdmission { .. } => diagnostic_code::DiagnosticCode::QueryReadAdmission,
2854 Self::SqlSurfaceMismatch { .. } => {
2855 diagnostic_code::DiagnosticCode::QuerySqlSurfaceMismatch
2856 }
2857 Self::SqlWriteBoundary { .. } => diagnostic_code::DiagnosticCode::QuerySqlWriteBoundary,
2858 Self::SchemaDdlAdmission { .. } => diagnostic_code::DiagnosticCode::SchemaDdlAdmission,
2859 Self::StaleSchemaRevision => diagnostic_code::DiagnosticCode::RuntimeConflict,
2860 }
2861 }
2862
2863 #[must_use]
2865 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2866 match self {
2867 Self::UnsupportedSqlFeature { feature } => {
2868 Some(diagnostic_code::DiagnosticDetail::UnsupportedSqlFeature { feature: *feature })
2869 }
2870 Self::SqlLowering { reason } => {
2871 Some(diagnostic_code::DiagnosticDetail::SqlLowering { reason: *reason })
2872 }
2873 Self::UnsupportedProjection { reason } => {
2874 Some(diagnostic_code::DiagnosticDetail::QueryProjection { reason: *reason })
2875 }
2876 Self::QueryReadAdmission { reason } => {
2877 Some(diagnostic_code::DiagnosticDetail::QueryReadAdmission { reason: *reason })
2878 }
2879 Self::SqlSurfaceMismatch { mismatch } => {
2880 Some(diagnostic_code::DiagnosticDetail::SqlSurfaceMismatch {
2881 mismatch: *mismatch,
2882 })
2883 }
2884 Self::SqlWriteBoundary { boundary } => {
2885 Some(diagnostic_code::DiagnosticDetail::SqlWriteBoundary {
2886 boundary: *boundary,
2887 })
2888 }
2889 Self::SchemaDdlAdmission { error } => {
2890 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2891 reason: error.diagnostic_code(),
2892 })
2893 }
2894 Self::ExactCountMetadataUnavailable
2895 | Self::NumericOverflow
2896 | Self::NumericNotRepresentable
2897 | Self::UnknownAggregateTargetField
2898 | Self::StaleSchemaRevision => None,
2899 }
2900 }
2901
2902 #[must_use]
2904 #[cold]
2905 #[inline(never)]
2906 pub const fn diagnostic_facts(&self) -> Vec<(diagnostic_code::DiagnosticFactTag, u64)> {
2907 Vec::new()
2908 }
2909}
2910
2911impl SchemaDdlAdmissionError {
2912 #[must_use]
2914 pub const fn diagnostic_code(&self) -> diagnostic_code::SchemaDdlAdmissionCode {
2915 match self {
2916 Self::MissingExpectedSchemaVersion => {
2917 diagnostic_code::SchemaDdlAdmissionCode::MissingExpectedSchemaVersion
2918 }
2919 Self::MissingNextSchemaVersion => {
2920 diagnostic_code::SchemaDdlAdmissionCode::MissingNextSchemaVersion
2921 }
2922 Self::StaleExpectedSchemaVersion => {
2923 diagnostic_code::SchemaDdlAdmissionCode::StaleExpectedSchemaVersion
2924 }
2925 Self::InvalidExpectedSchemaVersion => {
2926 diagnostic_code::SchemaDdlAdmissionCode::InvalidExpectedSchemaVersion
2927 }
2928 Self::InvalidNextSchemaVersion => {
2929 diagnostic_code::SchemaDdlAdmissionCode::InvalidNextSchemaVersion
2930 }
2931 Self::AcceptedSchemaChangeWithoutVersionBump => {
2932 diagnostic_code::SchemaDdlAdmissionCode::AcceptedSchemaChangeWithoutVersionBump
2933 }
2934 Self::EmptyVersionBump => diagnostic_code::SchemaDdlAdmissionCode::EmptyVersionBump,
2935 Self::VersionGap => diagnostic_code::SchemaDdlAdmissionCode::VersionGap,
2936 Self::VersionRollback => diagnostic_code::SchemaDdlAdmissionCode::VersionRollback,
2937 Self::FingerprintMethodMismatch => {
2938 diagnostic_code::SchemaDdlAdmissionCode::FingerprintMethodMismatch
2939 }
2940 Self::UnsupportedTransitionClass => {
2941 diagnostic_code::SchemaDdlAdmissionCode::UnsupportedTransitionClass
2942 }
2943 Self::PhysicalRunnerMissing => {
2944 diagnostic_code::SchemaDdlAdmissionCode::PhysicalRunnerMissing
2945 }
2946 Self::ValidationFailed => diagnostic_code::SchemaDdlAdmissionCode::ValidationFailed,
2947 Self::PublicationRaceLost => {
2948 diagnostic_code::SchemaDdlAdmissionCode::PublicationRaceLost
2949 }
2950 Self::InvalidAddColumnDefault => {
2951 diagnostic_code::SchemaDdlAdmissionCode::InvalidAddColumnDefault
2952 }
2953 Self::InvalidAlterColumnDefault => {
2954 diagnostic_code::SchemaDdlAdmissionCode::InvalidAlterColumnDefault
2955 }
2956 Self::GeneratedIndexDropRejected => {
2957 diagnostic_code::SchemaDdlAdmissionCode::GeneratedIndexDropRejected
2958 }
2959 Self::SchemaRewriteRequiresMigration => {
2960 diagnostic_code::SchemaDdlAdmissionCode::SchemaRewriteRequiresMigration
2961 }
2962 Self::SchemaTransitionBudgetExceeded { .. } => {
2963 diagnostic_code::SchemaDdlAdmissionCode::SchemaTransitionBudgetExceeded
2964 }
2965 Self::GeneratedFieldDefaultChangeRejected => {
2966 diagnostic_code::SchemaDdlAdmissionCode::GeneratedFieldDefaultChangeRejected
2967 }
2968 Self::GeneratedFieldNullabilityChangeRejected => {
2969 diagnostic_code::SchemaDdlAdmissionCode::GeneratedFieldNullabilityChangeRejected
2970 }
2971 Self::RowLayoutVersionExhausted => {
2972 diagnostic_code::SchemaDdlAdmissionCode::RowLayoutVersionExhausted
2973 }
2974 }
2975 }
2976}
2977
2978#[repr(u8)]
2985#[derive(Clone, Copy, Eq, PartialEq)]
2986pub enum ErrorClass {
2987 Corruption,
2988 IncompatiblePersistedFormat,
2989 NotFound,
2990 Internal,
2991 Conflict,
2992 Unsupported,
2993 InvariantViolation,
2994}
2995
2996impl ErrorClass {
2997 #[must_use]
2999 pub const fn diagnostic_code(self, origin: ErrorOrigin) -> diagnostic_code::DiagnosticCode {
3000 match self {
3001 Self::Corruption if matches!(origin, ErrorOrigin::Store) => {
3002 diagnostic_code::DiagnosticCode::StoreCorruption
3003 }
3004 Self::Corruption => diagnostic_code::DiagnosticCode::RuntimeCorruption,
3005 Self::IncompatiblePersistedFormat => {
3006 diagnostic_code::DiagnosticCode::RuntimeIncompatiblePersistedFormat
3007 }
3008 Self::NotFound if matches!(origin, ErrorOrigin::Store) => {
3009 diagnostic_code::DiagnosticCode::StoreNotFound
3010 }
3011 Self::NotFound => diagnostic_code::DiagnosticCode::RuntimeNotFound,
3012 Self::Internal => diagnostic_code::DiagnosticCode::RuntimeInternal,
3013 Self::Conflict => diagnostic_code::DiagnosticCode::RuntimeConflict,
3014 Self::Unsupported if matches!(origin, ErrorOrigin::Cursor) => {
3015 diagnostic_code::DiagnosticCode::QueryInvalidContinuationCursor
3016 }
3017 Self::Unsupported => diagnostic_code::DiagnosticCode::RuntimeUnsupported,
3018 Self::InvariantViolation if matches!(origin, ErrorOrigin::Store) => {
3019 diagnostic_code::DiagnosticCode::StoreInvariantViolation
3020 }
3021 Self::InvariantViolation => diagnostic_code::DiagnosticCode::RuntimeInvariantViolation,
3022 }
3023 }
3024}
3025
3026impl fmt::Debug for ErrorClass {
3027 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3028 write!(f, "{}", *self as u8)
3029 }
3030}
3031
3032#[repr(u8)]
3039#[derive(Clone, Copy, Eq, PartialEq)]
3040pub enum ErrorOrigin {
3041 Serialize,
3042 Store,
3043 Index,
3044 Identity,
3045 Query,
3046 Planner,
3047 Cursor,
3048 Recovery,
3049 Response,
3050 Executor,
3051 Interface,
3052}
3053
3054impl ErrorOrigin {
3055 #[must_use]
3057 pub const fn diagnostic_origin(self) -> diagnostic_code::ErrorOrigin {
3058 match self {
3059 Self::Serialize => diagnostic_code::ErrorOrigin::Serialize,
3060 Self::Store => diagnostic_code::ErrorOrigin::Store,
3061 Self::Index => diagnostic_code::ErrorOrigin::Index,
3062 Self::Identity => diagnostic_code::ErrorOrigin::Identity,
3063 Self::Query => diagnostic_code::ErrorOrigin::Query,
3064 Self::Planner => diagnostic_code::ErrorOrigin::Planner,
3065 Self::Cursor => diagnostic_code::ErrorOrigin::Cursor,
3066 Self::Recovery => diagnostic_code::ErrorOrigin::Recovery,
3067 Self::Response => diagnostic_code::ErrorOrigin::Response,
3068 Self::Executor => diagnostic_code::ErrorOrigin::Executor,
3069 Self::Interface => diagnostic_code::ErrorOrigin::Interface,
3070 }
3071 }
3072}
3073
3074impl fmt::Debug for ErrorOrigin {
3075 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3076 write!(f, "{}", *self as u8)
3077 }
3078}