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