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 pub(crate) fn sql_query_entity_not_found() -> Self {
394 Self::with_diagnostic_facts(
395 ErrorClass::NotFound,
396 ErrorOrigin::Interface,
397 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
398 boundary: diagnostic_code::RuntimeBoundaryCode::SqlQueryEntityNotFound,
399 }),
400 Vec::new(),
401 )
402 }
403
404 #[cold]
406 #[inline(never)]
407 pub(crate) fn execution_budget_exceeded(
408 resource: diagnostic_code::DiagnosticExecutionBudgetResource,
409 limit: u64,
410 observed: u64,
411 scope: diagnostic_code::DiagnosticExecutionBudgetScope,
412 lane: diagnostic_code::DiagnosticExecutionLane,
413 normalized_shape_fingerprint_prefix: u64,
414 ) -> Self {
415 Self::with_diagnostic_facts(
416 ErrorClass::Unsupported,
417 ErrorOrigin::Executor,
418 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
419 boundary: diagnostic_code::RuntimeBoundaryCode::ExecutionBudgetExceeded,
420 }),
421 vec![
422 (
423 diagnostic_code::DiagnosticFactTag::BudgetResource,
424 resource.raw(),
425 ),
426 (diagnostic_code::DiagnosticFactTag::Limit, limit),
427 (diagnostic_code::DiagnosticFactTag::Actual, observed),
428 (
429 diagnostic_code::DiagnosticFactTag::ExecutionBudgetScope,
430 scope.raw(),
431 ),
432 (
433 diagnostic_code::DiagnosticFactTag::ExecutionLane,
434 lane.raw(),
435 ),
436 (
437 diagnostic_code::DiagnosticFactTag::QueryShapeFingerprintPrefix,
438 normalized_shape_fingerprint_prefix,
439 ),
440 ],
441 )
442 }
443
444 #[cold]
446 #[inline(never)]
447 pub(crate) fn page_unit_too_large(
448 resource: diagnostic_code::DiagnosticExecutionBudgetResource,
449 limit: u64,
450 attempted: u64,
451 ) -> Self {
452 Self::with_diagnostic_facts(
453 ErrorClass::Unsupported,
454 ErrorOrigin::Executor,
455 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
456 boundary: diagnostic_code::RuntimeBoundaryCode::PageUnitTooLarge,
457 }),
458 vec![
459 (
460 diagnostic_code::DiagnosticFactTag::BudgetResource,
461 resource.raw(),
462 ),
463 (diagnostic_code::DiagnosticFactTag::Limit, limit),
464 (diagnostic_code::DiagnosticFactTag::Actual, attempted),
465 ],
466 )
467 }
468
469 #[cold]
474 #[inline(never)]
475 pub(crate) fn with_origin(self, origin: ErrorOrigin) -> Self {
476 match self.detail {
477 Some(ErrorDetail::DiagnosticFacts(detail)) => Self::with_diagnostic_facts(
478 self.class,
479 origin,
480 detail.diagnostic.detail().copied(),
481 detail.facts,
482 ),
483 _ => Self::classified(self.class, origin),
484 }
485 }
486
487 #[cold]
489 #[inline(never)]
490 pub(crate) fn index_invariant() -> Self {
491 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Index)
492 }
493
494 pub(crate) fn index_key_field_count_exceeds_max(
496 entity_tag: u64,
497 physical_generation: u64,
498 field_count: usize,
499 max_fields: usize,
500 ) -> Self {
501 Self::with_diagnostic_facts(
502 ErrorClass::InvariantViolation,
503 ErrorOrigin::Index,
504 None,
505 vec![
506 (diagnostic_code::DiagnosticFactTag::EntityTag, entity_tag),
507 (
508 diagnostic_code::DiagnosticFactTag::PhysicalGeneration,
509 physical_generation,
510 ),
511 (
512 diagnostic_code::DiagnosticFactTag::ComponentKind,
513 diagnostic_code::DiagnosticComponentKind::IndexKey.raw(),
514 ),
515 (
516 diagnostic_code::DiagnosticFactTag::ActualArity,
517 field_count as u64,
518 ),
519 (
520 diagnostic_code::DiagnosticFactTag::Maximum,
521 max_fields as u64,
522 ),
523 ],
524 )
525 }
526
527 pub(crate) fn index_expression_source_type_mismatch(
529 _index_name: &str,
530 _expression: impl Sized,
531 _expected: impl Sized,
532 _source_label: &str,
533 ) -> Self {
534 Self::index_invariant()
535 }
536
537 #[cold]
540 #[inline(never)]
541 pub(crate) fn planner_executor_invariant() -> Self {
542 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Planner)
543 }
544
545 #[cold]
548 #[inline(never)]
549 pub(crate) fn query_executor_invariant() -> Self {
550 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Query)
551 }
552
553 #[cold]
556 #[inline(never)]
557 pub(crate) fn cursor_executor_invariant() -> Self {
558 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Cursor)
559 }
560
561 #[cold]
563 #[inline(never)]
564 pub(crate) fn executor_invariant() -> Self {
565 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Executor)
566 }
567
568 #[cold]
570 #[inline(never)]
571 pub(crate) fn executor_internal() -> Self {
572 Self::new(ErrorClass::Internal, ErrorOrigin::Executor)
573 }
574
575 #[cold]
577 #[inline(never)]
578 pub(crate) fn executor_unsupported() -> Self {
579 Self::new(ErrorClass::Unsupported, ErrorOrigin::Executor)
580 }
581
582 #[cold]
584 #[inline(never)]
585 pub(crate) fn mutation_database_owned_field_explicit(
586 context: MutationDiagnosticContext,
587 field_id: u32,
588 ) -> Self {
589 Self::mutation_boundary_with_facts(
590 ErrorClass::Unsupported,
591 diagnostic_code::RuntimeBoundaryCode::MutationDatabaseOwnedFieldExplicit,
592 context.facts(Some(field_id)),
593 )
594 }
595
596 #[must_use]
598 #[cold]
599 #[inline(never)]
600 pub(crate) fn mutation_required_field_missing(
601 context: MutationDiagnosticContext,
602 field_id: u32,
603 ) -> Self {
604 Self::mutation_boundary_with_facts(
605 ErrorClass::Unsupported,
606 diagnostic_code::RuntimeBoundaryCode::MutationRequiredFieldMissing,
607 context.facts(Some(field_id)),
608 )
609 }
610
611 #[must_use]
613 #[cold]
614 #[inline(never)]
615 pub(crate) fn mutation_managed_timestamp_regression(
616 context: MutationDiagnosticContext,
617 ) -> Self {
618 Self::mutation_boundary_with_facts(
619 ErrorClass::InvariantViolation,
620 diagnostic_code::RuntimeBoundaryCode::MutationManagedTimestampRegression,
621 context.facts(None),
622 )
623 }
624
625 pub(crate) fn mutation_constraint_violation(context: AcceptedConstraintFactContext) -> Self {
627 Self::mutation_boundary_with_facts(
628 ErrorClass::InvariantViolation,
629 diagnostic_code::RuntimeBoundaryCode::ConstraintViolation,
630 context.facts(),
631 )
632 }
633
634 pub(crate) fn accepted_row_constraint_program_corrupt() -> Self {
636 Self {
637 class: ErrorClass::Corruption,
638 origin: ErrorOrigin::Executor,
639 detail: Some(ErrorDetail::Executor(
640 ExecutorErrorDetail::AcceptedRowConstraintProgramCorrupt,
641 )),
642 }
643 }
644
645 pub(crate) fn mutation_constraint_activation_write_blocked(
647 context: AcceptedConstraintFactContext,
648 ) -> Self {
649 Self::mutation_boundary_with_facts(
650 ErrorClass::Conflict,
651 diagnostic_code::RuntimeBoundaryCode::ConstraintActivationWriteBlocked,
652 context.facts(),
653 )
654 }
655
656 pub(crate) fn mutation_structural_field_unknown(_entity_path: &str, _field_name: &str) -> Self {
658 Self::executor_invariant()
659 }
660
661 pub(crate) fn scalar_page_cursor_boundary_order_required() -> Self {
663 Self::query_executor_invariant()
664 }
665
666 pub(crate) fn scalar_page_cursor_boundary_after_ordering_required() -> Self {
668 Self::query_executor_invariant()
669 }
670
671 pub(crate) fn scalar_page_pagination_after_ordering_required() -> Self {
673 Self::query_executor_invariant()
674 }
675
676 pub(crate) fn fast_stream_route_kind_request_match_required() -> Self {
678 Self::query_executor_invariant()
679 }
680
681 pub(crate) fn secondary_index_prefix_spec_required() -> Self {
683 Self::query_executor_invariant()
684 }
685
686 pub(crate) fn index_range_limit_spec_required() -> Self {
688 Self::query_executor_invariant()
689 }
690
691 #[cold]
693 #[inline(never)]
694 pub(crate) fn mutation_atomic_save_duplicate_key(
695 entity_tag: u64,
696 first_position: u32,
697 duplicate_position: u32,
698 ) -> Self {
699 Self::mutation_boundary_with_facts(
700 ErrorClass::Conflict,
701 diagnostic_code::RuntimeBoundaryCode::MutationBatchDuplicateKey,
702 vec![
703 (diagnostic_code::DiagnosticFactTag::EntityTag, entity_tag),
704 (
705 diagnostic_code::DiagnosticFactTag::FirstBatchPosition,
706 u64::from(first_position),
707 ),
708 (
709 diagnostic_code::DiagnosticFactTag::DuplicateBatchPosition,
710 u64::from(duplicate_position),
711 ),
712 ],
713 )
714 }
715
716 #[cold]
718 #[inline(never)]
719 pub(crate) fn mutation_batch_empty() -> Self {
720 Self::mutation_boundary_with_facts(
721 ErrorClass::Unsupported,
722 diagnostic_code::RuntimeBoundaryCode::MutationBatchEmpty,
723 vec![(diagnostic_code::DiagnosticFactTag::ActualCount, 0)],
724 )
725 }
726
727 #[cold]
729 #[inline(never)]
730 pub(crate) fn mutation_batch_too_many_items(actual_count: usize, limit: usize) -> Self {
731 Self::mutation_boundary_with_facts(
732 ErrorClass::Unsupported,
733 diagnostic_code::RuntimeBoundaryCode::MutationBatchTooManyItems,
734 vec![
735 (
736 diagnostic_code::DiagnosticFactTag::ActualCount,
737 actual_count as u64,
738 ),
739 (diagnostic_code::DiagnosticFactTag::Limit, limit as u64),
740 ],
741 )
742 }
743
744 #[cold]
746 #[inline(never)]
747 pub(crate) fn mutation_batch_staged_bytes_exceeded(
748 actual_bytes: Option<usize>,
749 limit: usize,
750 ) -> Self {
751 let mut facts = Vec::with_capacity(1 + usize::from(actual_bytes.is_some()));
752 if let Some(actual_bytes) = actual_bytes {
753 facts.push((
754 diagnostic_code::DiagnosticFactTag::ActualLength,
755 actual_bytes as u64,
756 ));
757 }
758 facts.push((diagnostic_code::DiagnosticFactTag::Limit, limit as u64));
759 Self::mutation_boundary_with_facts(
760 ErrorClass::Unsupported,
761 diagnostic_code::RuntimeBoundaryCode::MutationBatchStagedBytesExceeded,
762 facts,
763 )
764 }
765
766 #[cold]
768 #[inline(never)]
769 pub(crate) fn mutation_batch_result_bytes_exceeded(actual_bytes: usize, limit: usize) -> Self {
770 Self::mutation_boundary_with_facts(
771 ErrorClass::Unsupported,
772 diagnostic_code::RuntimeBoundaryCode::MutationBatchResultBytesExceeded,
773 vec![
774 (
775 diagnostic_code::DiagnosticFactTag::ActualLength,
776 actual_bytes as u64,
777 ),
778 (diagnostic_code::DiagnosticFactTag::Limit, limit as u64),
779 ],
780 )
781 }
782
783 #[cold]
785 #[inline(never)]
786 pub(crate) fn exact_key_batch_too_many_items(actual_count: usize, limit: usize) -> Self {
787 Self::exact_key_batch_boundary_with_facts(
788 diagnostic_code::RuntimeBoundaryCode::ExactKeyBatchTooManyItems,
789 vec![
790 (
791 diagnostic_code::DiagnosticFactTag::ActualCount,
792 actual_count as u64,
793 ),
794 (diagnostic_code::DiagnosticFactTag::Limit, limit as u64),
795 ],
796 )
797 }
798
799 #[cold]
801 #[inline(never)]
802 pub(crate) fn exact_key_batch_input_bytes_exceeded(actual_bytes: usize, limit: usize) -> Self {
803 Self::exact_key_batch_bytes_exceeded(
804 diagnostic_code::RuntimeBoundaryCode::ExactKeyBatchInputBytesExceeded,
805 actual_bytes,
806 limit,
807 )
808 }
809
810 #[cold]
812 #[inline(never)]
813 pub(crate) fn exact_key_batch_stored_bytes_exceeded(actual_bytes: usize, limit: usize) -> Self {
814 Self::exact_key_batch_bytes_exceeded(
815 diagnostic_code::RuntimeBoundaryCode::ExactKeyBatchStoredBytesExceeded,
816 actual_bytes,
817 limit,
818 )
819 }
820
821 #[cold]
823 #[inline(never)]
824 pub(crate) fn exact_key_batch_result_bytes_exceeded(actual_bytes: usize, limit: usize) -> Self {
825 Self::exact_key_batch_bytes_exceeded(
826 diagnostic_code::RuntimeBoundaryCode::ExactKeyBatchResultBytesExceeded,
827 actual_bytes,
828 limit,
829 )
830 }
831
832 #[cold]
833 #[inline(never)]
834 fn exact_key_batch_bytes_exceeded(
835 boundary: diagnostic_code::RuntimeBoundaryCode,
836 actual_bytes: usize,
837 limit: usize,
838 ) -> Self {
839 Self::exact_key_batch_boundary_with_facts(
840 boundary,
841 vec![
842 (
843 diagnostic_code::DiagnosticFactTag::ActualLength,
844 actual_bytes as u64,
845 ),
846 (diagnostic_code::DiagnosticFactTag::Limit, limit as u64),
847 ],
848 )
849 }
850
851 #[cold]
853 #[inline(never)]
854 pub(crate) fn mutation_batch_entity_mismatch(
855 batch_position: u32,
856 expected_entity_tag: u64,
857 actual_entity_tag: u64,
858 ) -> Self {
859 Self::mutation_boundary_with_facts(
860 ErrorClass::Conflict,
861 diagnostic_code::RuntimeBoundaryCode::MutationBatchEntityMismatch,
862 vec![
863 (
864 diagnostic_code::DiagnosticFactTag::BatchPosition,
865 u64::from(batch_position),
866 ),
867 (
868 diagnostic_code::DiagnosticFactTag::ExpectedEntityTag,
869 expected_entity_tag,
870 ),
871 (
872 diagnostic_code::DiagnosticFactTag::ActualEntityTag,
873 actual_entity_tag,
874 ),
875 ],
876 )
877 }
878
879 pub(crate) fn mutation_index_store_generation_changed(
881 _expected_generation: u64,
882 _observed_generation: u64,
883 ) -> Self {
884 Self::executor_invariant()
885 }
886
887 #[cold]
889 #[inline(never)]
890 pub(crate) fn planner_invariant() -> Self {
891 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Planner)
892 }
893
894 pub(crate) fn query_invalid_logical_plan() -> Self {
896 Self::planner_invariant()
897 }
898
899 pub(crate) fn store_invariant() -> Self {
901 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Store)
902 }
903
904 #[cold]
906 #[inline(never)]
907 pub(crate) fn store_internal() -> Self {
908 Self::new(ErrorClass::Internal, ErrorOrigin::Store)
909 }
910
911 pub(crate) fn commit_memory_id_unconfigured() -> Self {
913 Self::store_internal()
914 }
915
916 pub(crate) fn commit_store_uninitialized() -> Self {
918 Self::store_invariant()
919 }
920
921 pub(crate) fn commit_memory_id_mismatch(cached_id: u8, configured_id: u8) -> Self {
923 Self::with_diagnostic_facts(
924 ErrorClass::Internal,
925 ErrorOrigin::Store,
926 None,
927 vec![
928 (
929 diagnostic_code::DiagnosticFactTag::ExpectedMemoryId,
930 u64::from(cached_id),
931 ),
932 (
933 diagnostic_code::DiagnosticFactTag::ActualMemoryId,
934 u64::from(configured_id),
935 ),
936 ],
937 )
938 }
939
940 pub(crate) fn commit_memory_stable_key_mismatch(
942 _cached_key: &str,
943 _configured_key: &str,
944 ) -> Self {
945 Self::store_internal()
946 }
947
948 pub(crate) fn database_incarnation_generation_failed() -> Self {
950 Self::store_internal()
951 }
952
953 pub(crate) fn database_incarnation_invalid() -> Self {
955 Self::store_corruption()
956 }
957
958 pub(crate) fn recovery_unsupported_database_format(found: Option<u16>, required: u16) -> Self {
960 Self {
961 class: ErrorClass::IncompatiblePersistedFormat,
962 origin: ErrorOrigin::Recovery,
963 detail: Some(ErrorDetail::Recovery(
964 RecoveryErrorDetail::UnsupportedFormatVersion { found, required },
965 )),
966 }
967 }
968
969 pub(crate) fn recovery_malformed_database_format_marker(
971 reason: RecoveryFormatMarkerError,
972 ) -> Self {
973 Self {
974 class: ErrorClass::Corruption,
975 origin: ErrorOrigin::Recovery,
976 detail: Some(ErrorDetail::Recovery(
977 RecoveryErrorDetail::MalformedFormatMarker { reason },
978 )),
979 }
980 }
981
982 pub(crate) fn recovery_database_format_control_unavailable() -> Self {
984 Self::new(ErrorClass::Internal, ErrorOrigin::Recovery)
985 }
986
987 pub(crate) fn commit_control_memory_growth_failed() -> Self {
989 Self::store_internal()
990 }
991
992 #[cfg(not(test))]
994 pub(crate) fn database_format_memory_registration_failed(_err: impl Sized) -> Self {
995 Self::store_internal()
996 }
997
998 pub(crate) fn recovery_effect_verification_failed() -> Self {
1000 Self::store_corruption()
1001 }
1002
1003 #[cold]
1005 #[inline(never)]
1006 pub(crate) fn index_internal() -> Self {
1007 Self::new(ErrorClass::Internal, ErrorOrigin::Index)
1008 }
1009
1010 pub(crate) fn structural_index_removal_entity_key_required() -> Self {
1012 Self::index_internal()
1013 }
1014
1015 pub(crate) fn structural_index_insertion_entity_key_required() -> Self {
1017 Self::index_internal()
1018 }
1019
1020 pub(crate) fn index_commit_op_old_entity_key_required() -> Self {
1022 Self::index_internal()
1023 }
1024
1025 pub(crate) fn index_commit_op_new_entity_key_required() -> Self {
1027 Self::index_internal()
1028 }
1029
1030 #[cfg(test)]
1032 pub(crate) fn query_internal() -> Self {
1033 Self::new(ErrorClass::Internal, ErrorOrigin::Query)
1034 }
1035
1036 #[cold]
1038 #[inline(never)]
1039 pub(crate) fn query_unsupported() -> Self {
1040 Self::new(ErrorClass::Unsupported, ErrorOrigin::Query)
1041 }
1042
1043 #[cold]
1046 #[inline(never)]
1047 pub(crate) fn query_stale_accepted_schema_revision(
1048 expected_revision: u64,
1049 current_revision: Option<u64>,
1050 ) -> Self {
1051 let mut facts = Vec::with_capacity(1 + usize::from(current_revision.is_some()));
1052 facts.push((
1053 diagnostic_code::DiagnosticFactTag::ExpectedRevision,
1054 expected_revision,
1055 ));
1056 if let Some(current_revision) = current_revision {
1057 facts.push((
1058 diagnostic_code::DiagnosticFactTag::CurrentRevision,
1059 current_revision,
1060 ));
1061 }
1062 Self::with_diagnostic_facts(ErrorClass::Conflict, ErrorOrigin::Query, None, facts)
1063 }
1064
1065 #[cold]
1067 #[inline(never)]
1068 #[cfg(feature = "sql")]
1069 pub(crate) fn query_schema_ddl_admission(error: SchemaDdlAdmissionError) -> Self {
1070 Self {
1071 class: ErrorClass::Unsupported,
1072 origin: ErrorOrigin::Query,
1073 detail: Some(ErrorDetail::Query(QueryErrorDetail::SchemaDdlAdmission {
1074 error,
1075 })),
1076 }
1077 }
1078
1079 #[cold]
1081 #[inline(never)]
1082 pub(crate) fn query_numeric_overflow() -> Self {
1083 Self {
1084 class: ErrorClass::Unsupported,
1085 origin: ErrorOrigin::Query,
1086 detail: Some(ErrorDetail::Query(QueryErrorDetail::NumericOverflow)),
1087 }
1088 }
1089
1090 #[cold]
1093 #[inline(never)]
1094 pub(crate) fn query_numeric_not_representable() -> Self {
1095 Self {
1096 class: ErrorClass::Unsupported,
1097 origin: ErrorOrigin::Query,
1098 detail: Some(ErrorDetail::Query(
1099 QueryErrorDetail::NumericNotRepresentable,
1100 )),
1101 }
1102 }
1103
1104 #[cold]
1106 #[inline(never)]
1107 pub(crate) fn serialize_internal() -> Self {
1108 Self::new(ErrorClass::Internal, ErrorOrigin::Serialize)
1109 }
1110
1111 pub(crate) fn persisted_row_encode_failed(_detail: impl Sized) -> Self {
1113 Self::persisted_row_encode_internal()
1114 }
1115
1116 pub(crate) fn persisted_row_encode_internal() -> Self {
1118 Self::serialize_internal()
1119 }
1120
1121 pub(crate) fn persisted_row_field_encode_internal(_field_name: &str) -> Self {
1123 Self::persisted_row_encode_internal()
1124 }
1125
1126 #[cold]
1128 #[inline(never)]
1129 pub(crate) fn store_corruption() -> Self {
1130 Self::new(ErrorClass::Corruption, ErrorOrigin::Store)
1131 }
1132
1133 pub(crate) fn commit_corruption() -> Self {
1135 Self::store_corruption()
1136 }
1137
1138 pub(crate) fn commit_component_corruption() -> Self {
1140 Self::commit_corruption()
1141 }
1142
1143 pub(crate) fn commit_id_generation_failed() -> Self {
1145 Self::store_internal()
1146 }
1147
1148 pub(crate) fn commit_marker_payload_exceeds_u32_length_limit() -> Self {
1150 Self::store_unsupported()
1151 }
1152
1153 pub(crate) fn commit_component_length_invalid(actual_length: usize, limit: usize) -> Self {
1155 Self::with_diagnostic_facts(
1156 ErrorClass::Corruption,
1157 ErrorOrigin::Store,
1158 None,
1159 vec![
1160 (
1161 diagnostic_code::DiagnosticFactTag::ComponentKind,
1162 diagnostic_code::DiagnosticComponentKind::CommitDataKey.raw(),
1163 ),
1164 (
1165 diagnostic_code::DiagnosticFactTag::ActualLength,
1166 actual_length as u64,
1167 ),
1168 (diagnostic_code::DiagnosticFactTag::Limit, limit as u64),
1169 ],
1170 )
1171 }
1172
1173 pub(crate) fn commit_marker_exceeds_max_size() -> Self {
1175 Self::commit_corruption()
1176 }
1177
1178 pub(crate) fn commit_control_slot_exceeds_max_size() -> Self {
1180 Self::store_unsupported()
1181 }
1182
1183 pub(crate) fn commit_control_slot_marker_bytes_exceed_u32_length_limit() -> Self {
1185 Self::store_unsupported()
1186 }
1187
1188 pub(crate) fn startup_index_rebuild_invalid_data_key() -> Self {
1190 Self::store_corruption()
1191 }
1192
1193 #[cold]
1195 #[inline(never)]
1196 pub(crate) fn index_corruption() -> Self {
1197 Self::new(ErrorClass::Corruption, ErrorOrigin::Index)
1198 }
1199
1200 pub(crate) fn index_unique_validation_corruption() -> Self {
1202 Self::index_plan_index_corruption()
1203 }
1204
1205 pub(crate) fn structural_index_entry_corruption() -> Self {
1207 Self::index_plan_index_corruption()
1208 }
1209
1210 pub(crate) fn index_unique_validation_entity_key_required() -> Self {
1212 Self::index_invariant()
1213 }
1214
1215 pub(crate) fn index_unique_validation_row_deserialize_failed() -> Self {
1217 Self::index_plan_serialize_corruption()
1218 }
1219
1220 pub(crate) fn index_unique_validation_primary_key_decode_failed() -> Self {
1222 Self::index_plan_serialize_corruption()
1223 }
1224
1225 pub(crate) fn index_unique_validation_key_rebuild_failed() -> Self {
1227 Self::index_plan_serialize_corruption()
1228 }
1229
1230 pub(crate) fn index_unique_validation_row_required() -> Self {
1232 Self::index_plan_store_corruption()
1233 }
1234
1235 pub(crate) fn index_only_predicate_component_required() -> Self {
1237 Self::index_invariant()
1238 }
1239
1240 pub(crate) fn index_scan_continuation_anchor_within_envelope_required() -> Self {
1242 Self::index_invariant()
1243 }
1244
1245 pub(crate) fn index_scan_continuation_advancement_required() -> Self {
1247 Self::index_invariant()
1248 }
1249
1250 pub(crate) fn index_scan_key_corrupted_during(
1252 _context: &'static str,
1253 _err: impl Sized,
1254 ) -> Self {
1255 Self::index_corruption()
1256 }
1257
1258 pub(crate) fn index_projection_component_required(
1260 _index_name: &str,
1261 _component_index: usize,
1262 ) -> Self {
1263 Self::index_invariant()
1264 }
1265
1266 pub(crate) fn index_entry_decode_failed() -> Self {
1268 Self::index_corruption()
1269 }
1270
1271 pub(crate) fn serialize_corruption() -> Self {
1273 Self::new(ErrorClass::Corruption, ErrorOrigin::Serialize)
1274 }
1275
1276 pub(crate) fn persisted_row_decode_corruption() -> Self {
1278 Self::serialize_corruption()
1279 }
1280
1281 pub(crate) fn persisted_row_layout_outside_accepted_window(
1283 row_layout: u32,
1284 history_floor: u32,
1285 current_layout: u32,
1286 ) -> Self {
1287 Self::with_diagnostic_facts(
1288 ErrorClass::Corruption,
1289 ErrorOrigin::Serialize,
1290 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
1291 boundary:
1292 diagnostic_code::RuntimeBoundaryCode::PersistedRowLayoutOutsideAcceptedWindow,
1293 }),
1294 vec![
1295 (
1296 diagnostic_code::DiagnosticFactTag::RowLayout,
1297 u64::from(row_layout),
1298 ),
1299 (
1300 diagnostic_code::DiagnosticFactTag::HistoryFloor,
1301 u64::from(history_floor),
1302 ),
1303 (
1304 diagnostic_code::DiagnosticFactTag::CurrentLayout,
1305 u64::from(current_layout),
1306 ),
1307 ],
1308 )
1309 }
1310
1311 pub(crate) fn persisted_row_slot_count_mismatch(
1313 row_layout: u32,
1314 expected_slot_count: usize,
1315 actual_slot_count: usize,
1316 ) -> Self {
1317 Self::with_diagnostic_facts(
1318 ErrorClass::Corruption,
1319 ErrorOrigin::Serialize,
1320 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
1321 boundary: diagnostic_code::RuntimeBoundaryCode::PersistedRowSlotCountMismatch,
1322 }),
1323 vec![
1324 (
1325 diagnostic_code::DiagnosticFactTag::RowLayout,
1326 u64::from(row_layout),
1327 ),
1328 (
1329 diagnostic_code::DiagnosticFactTag::ExpectedSlotCount,
1330 expected_slot_count as u64,
1331 ),
1332 (
1333 diagnostic_code::DiagnosticFactTag::ActualSlotCount,
1334 actual_slot_count as u64,
1335 ),
1336 ],
1337 )
1338 }
1339
1340 pub(crate) fn persisted_row_field_decode_failed(field_name: &str, _detail: impl Sized) -> Self {
1342 Self::persisted_row_field_decode_corruption(field_name)
1343 }
1344
1345 pub(crate) fn persisted_row_field_decode_corruption(_field_name: &str) -> Self {
1347 Self::persisted_row_decode_corruption()
1348 }
1349
1350 pub(crate) fn persisted_row_field_kind_decode_failed(
1352 field_name: &str,
1353 _field_kind: impl fmt::Debug,
1354 _detail: impl Sized,
1355 ) -> Self {
1356 Self::persisted_row_field_decode_corruption(field_name)
1357 }
1358
1359 pub(crate) fn persisted_row_field_payload_exact_len_required(field_name: &str) -> Self {
1361 Self::persisted_row_field_decode_corruption(field_name)
1362 }
1363
1364 pub(crate) fn persisted_row_field_payload_must_be_empty(field_name: &str) -> Self {
1366 Self::persisted_row_field_decode_corruption(field_name)
1367 }
1368
1369 pub(crate) fn persisted_row_field_payload_invalid_byte(field_name: &str) -> Self {
1371 Self::persisted_row_field_decode_corruption(field_name)
1372 }
1373
1374 pub(crate) fn persisted_row_field_payload_non_finite(field_name: &str) -> Self {
1376 Self::persisted_row_field_decode_corruption(field_name)
1377 }
1378
1379 pub(crate) fn persisted_row_field_text_payload_invalid_utf8(field_name: &str) -> Self {
1381 Self::persisted_row_field_decode_corruption(field_name)
1382 }
1383
1384 pub(crate) fn persisted_row_slot_lookup_out_of_bounds(_model_path: &str, _slot: usize) -> Self {
1386 Self::index_invariant()
1387 }
1388
1389 pub(crate) fn persisted_row_slot_cache_lookup_out_of_bounds(
1391 _model_path: &str,
1392 _slot: usize,
1393 ) -> Self {
1394 Self::index_invariant()
1395 }
1396
1397 pub(crate) fn persisted_row_primary_key_not_primary_key_encodable(
1399 _data_key: impl fmt::Debug,
1400 _detail: impl Sized,
1401 ) -> Self {
1402 Self::persisted_row_decode_corruption()
1403 }
1404
1405 pub(crate) fn persisted_row_primary_key_slot_missing(_data_key: impl fmt::Debug) -> Self {
1407 Self::persisted_row_decode_corruption()
1408 }
1409
1410 pub(crate) fn persisted_row_key_mismatch() -> Self {
1412 Self::store_corruption()
1413 }
1414
1415 pub(crate) fn persisted_row_declared_field_missing(field_name: &str) -> Self {
1417 Self::persisted_row_field_decode_corruption(field_name)
1418 }
1419
1420 pub(crate) fn reverse_index_ordinal_overflow(
1422 _source_path: &str,
1423 _field_name: &str,
1424 _target_path: &str,
1425 _detail: impl Sized,
1426 ) -> Self {
1427 Self::index_internal()
1428 }
1429
1430 pub(crate) fn reverse_index_entry_corrupted(
1432 _source_path: &str,
1433 _field_name: &str,
1434 _target_path: &str,
1435 _index_key: impl fmt::Debug,
1436 _detail: impl Sized,
1437 ) -> Self {
1438 Self::index_corruption()
1439 }
1440
1441 pub(crate) fn relation_target_store_missing(
1443 _source_path: &str,
1444 _field_name: &str,
1445 _target_path: &str,
1446 _store_path: &str,
1447 _detail: impl Sized,
1448 ) -> Self {
1449 Self::executor_internal()
1450 }
1451
1452 pub(crate) fn relation_target_primary_key_arity_mismatch(
1454 expected_arity: usize,
1455 actual_arity: usize,
1456 ) -> Self {
1457 Self::with_diagnostic_facts(
1458 ErrorClass::Internal,
1459 ErrorOrigin::Executor,
1460 None,
1461 vec![
1462 (
1463 diagnostic_code::DiagnosticFactTag::ComponentKind,
1464 diagnostic_code::DiagnosticComponentKind::RelationTargetPrimaryKey.raw(),
1465 ),
1466 (
1467 diagnostic_code::DiagnosticFactTag::ExpectedArity,
1468 expected_arity as u64,
1469 ),
1470 (
1471 diagnostic_code::DiagnosticFactTag::ActualArity,
1472 actual_arity as u64,
1473 ),
1474 ],
1475 )
1476 }
1477
1478 pub(crate) fn relation_target_key_decode_failed(
1480 _context_label: &str,
1481 _source_path: &str,
1482 _field_name: &str,
1483 _target_path: &str,
1484 _detail: impl Sized,
1485 ) -> Self {
1486 Self::identity_corruption()
1487 }
1488
1489 pub(crate) fn relation_target_entity_mismatch(
1491 _context_label: &str,
1492 _source_path: &str,
1493 _field_name: &str,
1494 _target_path: &str,
1495 _target_entity_name: &str,
1496 expected_tag: u64,
1497 actual_tag: u64,
1498 ) -> Self {
1499 Self::with_diagnostic_facts(
1500 ErrorClass::Corruption,
1501 ErrorOrigin::Store,
1502 None,
1503 vec![
1504 (
1505 diagnostic_code::DiagnosticFactTag::ExpectedEntityTag,
1506 expected_tag,
1507 ),
1508 (
1509 diagnostic_code::DiagnosticFactTag::ActualEntityTag,
1510 actual_tag,
1511 ),
1512 ],
1513 )
1514 }
1515
1516 pub(crate) fn relation_source_row_decode_failed(
1518 _source_path: &str,
1519 _field_name: &str,
1520 _target_path: &str,
1521 _detail: impl Sized,
1522 ) -> Self {
1523 Self::persisted_row_decode_corruption()
1524 }
1525
1526 pub(crate) fn relation_source_row_unsupported_scalar_relation_key(
1528 _source_path: &str,
1529 _field_name: &str,
1530 _target_path: &str,
1531 ) -> Self {
1532 Self::persisted_row_decode_corruption()
1533 }
1534
1535 pub(crate) fn relation_source_row_unsupported_key_kind(_field_kind: impl fmt::Debug) -> Self {
1537 Self::persisted_row_decode_corruption()
1538 }
1539
1540 pub(crate) fn bytes_covering_component_payload_empty() -> Self {
1542 Self::index_corruption()
1543 }
1544
1545 pub(crate) fn bytes_covering_bool_payload_truncated() -> Self {
1547 Self::index_corruption()
1548 }
1549
1550 pub(crate) fn bytes_covering_component_payload_invalid_length() -> Self {
1552 Self::index_corruption()
1553 }
1554
1555 pub(crate) fn bytes_covering_bool_payload_invalid_value() -> Self {
1557 Self::index_corruption()
1558 }
1559
1560 pub(crate) fn bytes_covering_text_payload_invalid_terminator() -> Self {
1562 Self::index_corruption()
1563 }
1564
1565 pub(crate) fn bytes_covering_text_payload_trailing_bytes() -> Self {
1567 Self::index_corruption()
1568 }
1569
1570 pub(crate) fn bytes_covering_text_payload_invalid_utf8() -> Self {
1572 Self::index_corruption()
1573 }
1574
1575 pub(crate) fn bytes_covering_text_payload_invalid_escape_byte() -> Self {
1577 Self::index_corruption()
1578 }
1579
1580 pub(crate) fn bytes_covering_text_payload_missing_terminator() -> Self {
1582 Self::index_corruption()
1583 }
1584
1585 pub(crate) fn identity_corruption() -> Self {
1587 Self::new(ErrorClass::Corruption, ErrorOrigin::Identity)
1588 }
1589
1590 pub(crate) fn identity_state_corruption() -> Self {
1592 Self::identity_corruption()
1593 }
1594
1595 pub(crate) fn identity_state_conflict() -> Self {
1597 Self::new(ErrorClass::Conflict, ErrorOrigin::Identity)
1598 }
1599
1600 pub(crate) fn identity_state_capacity_exhausted() -> Self {
1602 Self::new(ErrorClass::Unsupported, ErrorOrigin::Identity)
1603 }
1604
1605 pub(crate) fn identity_exhausted() -> Self {
1607 Self::new(ErrorClass::Unsupported, ErrorOrigin::Identity)
1608 }
1609
1610 pub(crate) fn identity_candidate_count_exhausted() -> Self {
1612 Self::new(ErrorClass::Unsupported, ErrorOrigin::Identity)
1613 }
1614
1615 #[cold]
1617 #[inline(never)]
1618 pub(crate) fn store_unsupported() -> Self {
1619 Self::new(ErrorClass::Unsupported, ErrorOrigin::Store)
1620 }
1621
1622 pub(crate) fn schema_application_conflict() -> Self {
1624 Self::new(ErrorClass::Conflict, ErrorOrigin::Store)
1625 }
1626
1627 pub(crate) fn schema_migration(reason: diagnostic_code::SchemaMigrationCode) -> Self {
1629 let class = match reason.diagnostic_code() {
1630 diagnostic_code::DiagnosticCode::RuntimeConflict => ErrorClass::Conflict,
1631 diagnostic_code::DiagnosticCode::RuntimeCorruption => ErrorClass::Corruption,
1632 diagnostic_code::DiagnosticCode::RuntimeUnsupported => ErrorClass::Unsupported,
1633 _ => ErrorClass::Internal,
1634 };
1635 Self {
1636 class,
1637 origin: ErrorOrigin::Store,
1638 detail: Some(ErrorDetail::Store(StoreError::SchemaMigration { reason })),
1639 }
1640 }
1641
1642 pub(crate) fn schema_ddl_publication_race_lost(_entity_path: &str) -> Self {
1644 Self {
1645 class: ErrorClass::Unsupported,
1646 origin: ErrorOrigin::Store,
1647 detail: Some(ErrorDetail::Store(StoreError::SchemaDdlPublicationRaceLost)),
1648 }
1649 }
1650
1651 #[cfg(feature = "sql")]
1653 pub(crate) fn schema_ddl_rewrite_requires_migration(_entity_path: &str) -> Self {
1654 Self {
1655 class: ErrorClass::Unsupported,
1656 origin: ErrorOrigin::Store,
1657 detail: Some(ErrorDetail::Store(
1658 StoreError::SchemaDdlRewriteRequiresMigration,
1659 )),
1660 }
1661 }
1662
1663 pub(crate) fn journal_mutation_revision_exhausted() -> Self {
1665 Self {
1666 class: ErrorClass::Unsupported,
1667 origin: ErrorOrigin::Store,
1668 detail: Some(ErrorDetail::Store(
1669 StoreError::JournalMutationRevisionExhausted,
1670 )),
1671 }
1672 }
1673
1674 pub(crate) fn schema_transition_budget_exceeded(
1676 resource: SchemaTransitionBudgetResource,
1677 ) -> Self {
1678 Self {
1679 class: ErrorClass::Unsupported,
1680 origin: ErrorOrigin::Store,
1681 detail: Some(ErrorDetail::Store(
1682 StoreError::SchemaTransitionBudgetExceeded { resource },
1683 )),
1684 }
1685 }
1686
1687 pub(crate) fn unsupported_entity_tag_in_data_store(
1689 _entity_tag: crate::types::EntityTag,
1690 ) -> Self {
1691 Self::store_unsupported()
1692 }
1693
1694 #[cfg(not(test))]
1696 pub(crate) fn commit_memory_id_registration_failed(_err: impl Sized) -> Self {
1697 Self::store_internal()
1698 }
1699
1700 pub(crate) fn index_unsupported() -> Self {
1702 Self::new(ErrorClass::Unsupported, ErrorOrigin::Index)
1703 }
1704
1705 pub(crate) fn index_component_exceeds_max_size_at(
1707 entity_tag: u64,
1708 physical_generation: u64,
1709 component_index: usize,
1710 actual_length: usize,
1711 limit: usize,
1712 ) -> Self {
1713 Self::with_diagnostic_facts(
1714 ErrorClass::Unsupported,
1715 ErrorOrigin::Index,
1716 None,
1717 vec![
1718 (diagnostic_code::DiagnosticFactTag::EntityTag, entity_tag),
1719 (
1720 diagnostic_code::DiagnosticFactTag::PhysicalGeneration,
1721 physical_generation,
1722 ),
1723 (
1724 diagnostic_code::DiagnosticFactTag::ComponentIndex,
1725 component_index as u64,
1726 ),
1727 (
1728 diagnostic_code::DiagnosticFactTag::ComponentKind,
1729 diagnostic_code::DiagnosticComponentKind::IndexKeyComponent.raw(),
1730 ),
1731 (
1732 diagnostic_code::DiagnosticFactTag::ActualLength,
1733 actual_length as u64,
1734 ),
1735 (diagnostic_code::DiagnosticFactTag::Limit, limit as u64),
1736 ],
1737 )
1738 }
1739
1740 pub(crate) fn index_component_exceeds_max_size() -> Self {
1743 Self::index_unsupported()
1744 }
1745
1746 pub(crate) fn serialize_unsupported() -> Self {
1748 Self::new(ErrorClass::Unsupported, ErrorOrigin::Serialize)
1749 }
1750
1751 pub(crate) fn cursor_invalid_continuation() -> Self {
1753 Self::new(ErrorClass::Unsupported, ErrorOrigin::Cursor)
1754 }
1755
1756 pub(crate) fn serialize_incompatible_persisted_format() -> Self {
1758 Self::new(
1759 ErrorClass::IncompatiblePersistedFormat,
1760 ErrorOrigin::Serialize,
1761 )
1762 }
1763
1764 #[cfg(feature = "sql")]
1767 pub(crate) fn query_unsupported_sql_feature(feature: diagnostic_code::SqlFeatureCode) -> Self {
1768 Self {
1769 class: ErrorClass::Unsupported,
1770 origin: ErrorOrigin::Query,
1771 detail: Some(ErrorDetail::Query(
1772 QueryErrorDetail::UnsupportedSqlFeature { feature },
1773 )),
1774 }
1775 }
1776
1777 #[cfg(feature = "sql")]
1780 pub(crate) fn query_sql_lowering(reason: diagnostic_code::SqlLoweringCode) -> Self {
1781 Self {
1782 class: ErrorClass::Unsupported,
1783 origin: ErrorOrigin::Query,
1784 detail: Some(ErrorDetail::Query(QueryErrorDetail::SqlLowering { reason })),
1785 }
1786 }
1787
1788 #[cfg(feature = "sql")]
1790 pub(crate) fn query_sql_lowering_with_facts(
1791 reason: diagnostic_code::SqlLoweringCode,
1792 facts: Vec<(diagnostic_code::DiagnosticFactTag, u64)>,
1793 ) -> Self {
1794 Self::with_diagnostic_facts(
1795 ErrorClass::Unsupported,
1796 ErrorOrigin::Query,
1797 Some(diagnostic_code::DiagnosticDetail::SqlLowering { reason }),
1798 facts,
1799 )
1800 }
1801
1802 pub(crate) fn query_unsupported_projection(
1805 reason: diagnostic_code::QueryProjectionCode,
1806 ) -> Self {
1807 Self {
1808 class: ErrorClass::Unsupported,
1809 origin: ErrorOrigin::Query,
1810 detail: Some(ErrorDetail::Query(
1811 QueryErrorDetail::UnsupportedProjection { reason },
1812 )),
1813 }
1814 }
1815
1816 pub(crate) fn query_unknown_aggregate_target_field() -> Self {
1818 Self {
1819 class: ErrorClass::Unsupported,
1820 origin: ErrorOrigin::Query,
1821 detail: Some(ErrorDetail::Query(
1822 QueryErrorDetail::UnknownAggregateTargetField,
1823 )),
1824 }
1825 }
1826
1827 #[cfg(feature = "sql")]
1830 pub(crate) fn query_sql_surface_mismatch(
1831 mismatch: diagnostic_code::SqlSurfaceMismatchCode,
1832 ) -> Self {
1833 Self {
1834 class: ErrorClass::Unsupported,
1835 origin: ErrorOrigin::Query,
1836 detail: Some(ErrorDetail::Query(QueryErrorDetail::SqlSurfaceMismatch {
1837 mismatch,
1838 })),
1839 }
1840 }
1841
1842 pub(crate) fn query_sql_write_boundary(
1844 boundary: diagnostic_code::SqlWriteBoundaryCode,
1845 ) -> Self {
1846 Self {
1847 class: ErrorClass::Unsupported,
1848 origin: ErrorOrigin::Query,
1849 detail: Some(ErrorDetail::Query(QueryErrorDetail::SqlWriteBoundary {
1850 boundary,
1851 })),
1852 }
1853 }
1854
1855 pub(crate) fn query_sql_write_boundary_with_facts(
1857 boundary: diagnostic_code::SqlWriteBoundaryCode,
1858 facts: Vec<(diagnostic_code::DiagnosticFactTag, u64)>,
1859 ) -> Self {
1860 Self::with_diagnostic_facts(
1861 ErrorClass::Unsupported,
1862 ErrorOrigin::Query,
1863 Some(diagnostic_code::DiagnosticDetail::SqlWriteBoundary { boundary }),
1864 facts,
1865 )
1866 }
1867
1868 pub fn store_not_found(_key: impl Sized) -> Self {
1869 Self {
1870 class: ErrorClass::NotFound,
1871 origin: ErrorOrigin::Store,
1872 detail: Some(ErrorDetail::Store(StoreError::NotFound)),
1873 }
1874 }
1875
1876 pub fn unsupported_entity_path(_path: impl Sized) -> Self {
1878 Self::store_unsupported()
1879 }
1880
1881 #[cold]
1883 #[inline(never)]
1884 pub(crate) fn index_plan_corruption(origin: ErrorOrigin) -> Self {
1885 Self::new(ErrorClass::Corruption, origin)
1886 }
1887
1888 #[cold]
1890 #[inline(never)]
1891 pub(crate) fn index_plan_index_corruption() -> Self {
1892 Self::index_plan_corruption(ErrorOrigin::Index)
1893 }
1894
1895 #[cold]
1897 #[inline(never)]
1898 pub(crate) fn index_plan_store_corruption() -> Self {
1899 Self::index_plan_corruption(ErrorOrigin::Store)
1900 }
1901
1902 #[cold]
1904 #[inline(never)]
1905 pub(crate) fn index_plan_serialize_corruption() -> Self {
1906 Self::index_plan_corruption(ErrorOrigin::Serialize)
1907 }
1908
1909 #[cfg(test)]
1911 pub(crate) fn index_plan_invariant(origin: ErrorOrigin) -> Self {
1912 Self::new(ErrorClass::InvariantViolation, origin)
1913 }
1914
1915 #[cfg(test)]
1917 pub(crate) fn index_plan_store_invariant() -> Self {
1918 Self::index_plan_invariant(ErrorOrigin::Store)
1919 }
1920
1921 pub(crate) fn index_conflict() -> Self {
1927 Self::new(ErrorClass::Conflict, ErrorOrigin::Index)
1928 }
1929}
1930
1931impl From<diagnostic_code::QueryReadAdmissionCode> for InternalError {
1932 fn from(reason: diagnostic_code::QueryReadAdmissionCode) -> Self {
1933 Self {
1934 class: ErrorClass::Unsupported,
1935 origin: ErrorOrigin::Query,
1936 detail: Some(ErrorDetail::Query(QueryErrorDetail::QueryReadAdmission {
1937 reason,
1938 })),
1939 }
1940 }
1941}
1942
1943impl fmt::Debug for InternalError {
1944 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1945 fmt_compact_diagnostic(
1946 f,
1947 self.diagnostic_code(),
1948 self.detail
1949 .as_ref()
1950 .and_then(ErrorDetail::diagnostic_detail),
1951 )
1952 }
1953}
1954
1955impl fmt::Display for InternalError {
1956 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1957 f.write_str(self.message())
1958 }
1959}
1960
1961impl std::error::Error for InternalError {}
1962
1963#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq)]
1972pub enum ConstraintValuePathComponent {
1973 RootField { field_id: u32 },
1975
1976 RecordMember {
1978 composite_type_id: u32,
1979 member_id: u32,
1980 },
1981
1982 TupleElement {
1984 composite_type_id: u32,
1985 ordinal: u32,
1986 },
1987
1988 Newtype { composite_type_id: u32 },
1990
1991 EnumVariant { enum_type_id: u32, variant_id: u32 },
1993
1994 ListElement { index: u32 },
1996
1997 SetElement { index: u32 },
1999
2000 MapEntryKey { index: u32 },
2002
2003 MapEntryValue { index: u32 },
2005}
2006
2007impl fmt::Display for ConstraintValuePathComponent {
2008 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2009 match self {
2010 Self::RootField { field_id } => write!(f, "field#{field_id}"),
2011 Self::RecordMember {
2012 composite_type_id,
2013 member_id,
2014 } => write!(f, "record#{composite_type_id}.member#{member_id}"),
2015 Self::TupleElement {
2016 composite_type_id,
2017 ordinal,
2018 } => write!(f, "tuple#{composite_type_id}[{ordinal}]"),
2019 Self::Newtype { composite_type_id } => write!(f, "newtype#{composite_type_id}"),
2020 Self::EnumVariant {
2021 enum_type_id,
2022 variant_id,
2023 } => write!(f, "enum#{enum_type_id}.variant#{variant_id}"),
2024 Self::ListElement { index } => write!(f, "list[{index}]"),
2025 Self::SetElement { index } => write!(f, "set[{index}]"),
2026 Self::MapEntryKey { index } => write!(f, "map[{index}].key"),
2027 Self::MapEntryValue { index } => write!(f, "map[{index}].value"),
2028 }
2029 }
2030}
2031
2032#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
2039pub struct ConstraintValuePath {
2040 components: Vec<ConstraintValuePathComponent>,
2041}
2042
2043impl ConstraintValuePath {
2044 #[must_use]
2046 pub(crate) const fn new(components: Vec<ConstraintValuePathComponent>) -> Self {
2047 Self { components }
2048 }
2049
2050 #[must_use]
2052 pub const fn components(&self) -> &[ConstraintValuePathComponent] {
2053 self.components.as_slice()
2054 }
2055}
2056
2057impl fmt::Display for ConstraintValuePath {
2058 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2059 for (ordinal, component) in self.components.iter().enumerate() {
2060 if ordinal != 0 {
2061 f.write_str("/")?;
2062 }
2063 component.fmt(f)?;
2064 }
2065 Ok(())
2066 }
2067}
2068
2069#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
2078pub struct ConstraintValidationFindingOutput {
2079 accepted_schema_fingerprint: [u8; 16],
2080 entity_tag: u64,
2081 constraint_id: u32,
2082 primary_key: Vec<u8>,
2083 field_ids: Vec<u32>,
2084 value_path: Option<ConstraintValuePath>,
2085 error_code: u16,
2086}
2087
2088impl ConstraintValidationFindingOutput {
2089 #[must_use]
2091 pub(crate) const fn new(
2092 accepted_schema_fingerprint: [u8; 16],
2093 entity_tag: u64,
2094 constraint_id: u32,
2095 primary_key: Vec<u8>,
2096 field_ids: Vec<u32>,
2097 value_path: Option<ConstraintValuePath>,
2098 error_code: u16,
2099 ) -> Self {
2100 Self {
2101 accepted_schema_fingerprint,
2102 entity_tag,
2103 constraint_id,
2104 primary_key,
2105 field_ids,
2106 value_path,
2107 error_code,
2108 }
2109 }
2110
2111 #[must_use]
2113 pub const fn accepted_schema_fingerprint(&self) -> [u8; 16] {
2114 self.accepted_schema_fingerprint
2115 }
2116
2117 #[must_use]
2119 pub const fn entity_tag(&self) -> u64 {
2120 self.entity_tag
2121 }
2122
2123 #[must_use]
2125 pub const fn constraint_id(&self) -> u32 {
2126 self.constraint_id
2127 }
2128
2129 #[must_use]
2131 pub const fn primary_key(&self) -> &[u8] {
2132 self.primary_key.as_slice()
2133 }
2134
2135 #[must_use]
2137 pub const fn field_ids(&self) -> &[u32] {
2138 self.field_ids.as_slice()
2139 }
2140
2141 #[must_use]
2143 pub const fn value_path(&self) -> Option<&ConstraintValuePath> {
2144 self.value_path.as_ref()
2145 }
2146
2147 #[must_use]
2149 pub const fn error_code(&self) -> diagnostic_code::ErrorCode {
2150 diagnostic_code::ErrorCode::from_raw(self.error_code)
2151 }
2152
2153 #[must_use]
2155 pub const fn error_class(&self) -> diagnostic_code::ErrorClass {
2156 self.error_code().class()
2157 }
2158}
2159
2160#[derive(Clone)]
2162pub(crate) struct AcceptedConstraintFactContext {
2163 fingerprint_method: u8,
2164 accepted_schema_fingerprint: [u8; 16],
2165 entity_tag: u64,
2166 constraint_id: u32,
2167 constraint_kind: diagnostic_code::DiagnosticConstraintKind,
2168 mutation: Option<MutationDiagnosticContext>,
2169 value_path: Option<ConstraintValuePath>,
2170}
2171
2172impl AcceptedConstraintFactContext {
2173 #[must_use]
2174 pub(crate) fn write_admission(
2175 fingerprint_method: u8,
2176 accepted_schema_fingerprint: [u8; 16],
2177 entity_tag: u64,
2178 constraint_id: u32,
2179 constraint_kind: diagnostic_code::DiagnosticConstraintKind,
2180 mutation: Option<MutationDiagnosticContext>,
2181 value_path: Option<ConstraintValuePath>,
2182 ) -> Self {
2183 debug_assert!(mutation.is_none_or(|context| context.entity_tag() == entity_tag));
2184 Self {
2185 fingerprint_method,
2186 accepted_schema_fingerprint,
2187 entity_tag,
2188 constraint_id,
2189 constraint_kind,
2190 mutation,
2191 value_path,
2192 }
2193 }
2194
2195 fn facts(self) -> Vec<(diagnostic_code::DiagnosticFactTag, u64)> {
2196 let high = u64::from_be_bytes([
2197 self.accepted_schema_fingerprint[0],
2198 self.accepted_schema_fingerprint[1],
2199 self.accepted_schema_fingerprint[2],
2200 self.accepted_schema_fingerprint[3],
2201 self.accepted_schema_fingerprint[4],
2202 self.accepted_schema_fingerprint[5],
2203 self.accepted_schema_fingerprint[6],
2204 self.accepted_schema_fingerprint[7],
2205 ]);
2206 let low = u64::from_be_bytes([
2207 self.accepted_schema_fingerprint[8],
2208 self.accepted_schema_fingerprint[9],
2209 self.accepted_schema_fingerprint[10],
2210 self.accepted_schema_fingerprint[11],
2211 self.accepted_schema_fingerprint[12],
2212 self.accepted_schema_fingerprint[13],
2213 self.accepted_schema_fingerprint[14],
2214 self.accepted_schema_fingerprint[15],
2215 ]);
2216 let path_len = self
2217 .value_path
2218 .as_ref()
2219 .map_or(0, |path| path.components().len());
2220 let mutation_fact_count = self.mutation.map_or(0, |mutation| {
2221 1 + usize::from(mutation.batch_position.is_some())
2222 });
2223 let mut facts = Vec::with_capacity(7 + mutation_fact_count + path_len);
2224 facts.push((
2225 diagnostic_code::DiagnosticFactTag::AcceptedSchemaFingerprintMethod,
2226 u64::from(self.fingerprint_method),
2227 ));
2228 facts.push((
2229 diagnostic_code::DiagnosticFactTag::AcceptedSchemaFingerprintHigh,
2230 high,
2231 ));
2232 facts.push((
2233 diagnostic_code::DiagnosticFactTag::AcceptedSchemaFingerprintLow,
2234 low,
2235 ));
2236 facts.push((
2237 diagnostic_code::DiagnosticFactTag::EntityTag,
2238 self.entity_tag,
2239 ));
2240 facts.push((
2241 diagnostic_code::DiagnosticFactTag::ConstraintId,
2242 u64::from(self.constraint_id),
2243 ));
2244 facts.push((
2245 diagnostic_code::DiagnosticFactTag::ConstraintKind,
2246 self.constraint_kind.raw(),
2247 ));
2248 facts.push((
2249 diagnostic_code::DiagnosticFactTag::ConstraintContext,
2250 diagnostic_code::DiagnosticConstraintContext::WriteAdmission.raw(),
2251 ));
2252 if let Some(mutation) = self.mutation {
2253 mutation.append_operation_facts(&mut facts);
2254 }
2255 if let Some(path) = self.value_path {
2256 for component in path.components {
2257 facts.push(constraint_value_path_fact(component));
2258 }
2259 }
2260 debug_assert!(facts.len() <= diagnostic_code::MAX_PUBLIC_DIAGNOSTIC_FACTS);
2261 facts
2262 }
2263}
2264
2265fn constraint_value_path_fact(
2266 component: ConstraintValuePathComponent,
2267) -> (diagnostic_code::DiagnosticFactTag, u64) {
2268 use diagnostic_code::DiagnosticFactTag;
2269 match component {
2270 ConstraintValuePathComponent::RootField { field_id } => {
2271 (DiagnosticFactTag::RootField, u64::from(field_id))
2272 }
2273 ConstraintValuePathComponent::RecordMember {
2274 composite_type_id,
2275 member_id,
2276 } => (
2277 DiagnosticFactTag::RecordMember,
2278 diagnostic_code::pack_u32_pair(composite_type_id, member_id),
2279 ),
2280 ConstraintValuePathComponent::TupleElement {
2281 composite_type_id,
2282 ordinal,
2283 } => (
2284 DiagnosticFactTag::TupleElement,
2285 diagnostic_code::pack_u32_pair(composite_type_id, ordinal),
2286 ),
2287 ConstraintValuePathComponent::Newtype { composite_type_id } => {
2288 (DiagnosticFactTag::Newtype, u64::from(composite_type_id))
2289 }
2290 ConstraintValuePathComponent::EnumVariant {
2291 enum_type_id,
2292 variant_id,
2293 } => (
2294 DiagnosticFactTag::EnumVariant,
2295 diagnostic_code::pack_u32_pair(enum_type_id, variant_id),
2296 ),
2297 ConstraintValuePathComponent::ListElement { index } => {
2298 (DiagnosticFactTag::ListElement, u64::from(index))
2299 }
2300 ConstraintValuePathComponent::SetElement { index } => {
2301 (DiagnosticFactTag::SetElement, u64::from(index))
2302 }
2303 ConstraintValuePathComponent::MapEntryKey { index } => {
2304 (DiagnosticFactTag::MapEntryKey, u64::from(index))
2305 }
2306 ConstraintValuePathComponent::MapEntryValue { index } => {
2307 (DiagnosticFactTag::MapEntryValue, u64::from(index))
2308 }
2309 }
2310}
2311
2312pub enum ErrorDetail {
2320 DiagnosticFacts(Box<DiagnosticFactDetail>),
2322 Executor(ExecutorErrorDetail),
2324 Store(StoreError),
2325 Query(QueryErrorDetail),
2326 Recovery(RecoveryErrorDetail),
2327 }
2330
2331pub enum ExecutorErrorDetail {
2333 MutationRequiredFieldMissing,
2335 MutationManagedTimestampRegression,
2337 MutationDatabaseOwnedFieldExplicit,
2339 MutationBatchEmpty,
2341 MutationBatchTooManyItems,
2343 MutationBatchStagedBytesExceeded,
2345 MutationBatchResultBytesExceeded,
2347 MutationBatchEntityMismatch,
2349 MutationBatchDuplicateKey,
2351 AcceptedRowConstraintProgramCorrupt,
2353}
2354
2355pub enum RecoveryErrorDetail {
2362 UnsupportedFormatVersion { found: Option<u16>, required: u16 },
2363
2364 MalformedFormatMarker { reason: RecoveryFormatMarkerError },
2365}
2366
2367#[derive(Clone, Copy, Eq, PartialEq)]
2369pub enum RecoveryFormatMarkerError {
2370 Magic,
2371 Checksum,
2372 State,
2373}
2374
2375impl RecoveryFormatMarkerError {
2376 const fn diagnostic_decode_reason(self) -> diagnostic_code::DiagnosticDecodeReason {
2377 match self {
2378 Self::Magic => diagnostic_code::DiagnosticDecodeReason::RecoveryMarkerMagic,
2379 Self::Checksum => diagnostic_code::DiagnosticDecodeReason::RecoveryMarkerChecksum,
2380 Self::State => diagnostic_code::DiagnosticDecodeReason::RecoveryMarkerState,
2381 }
2382 }
2383}
2384
2385pub enum StoreError {
2393 NotFound,
2394
2395 Corrupt,
2396
2397 InvariantViolation,
2398
2399 SchemaDdlPublicationRaceLost,
2400
2401 SchemaDdlRewriteRequiresMigration,
2402
2403 SchemaMigration {
2404 reason: diagnostic_code::SchemaMigrationCode,
2405 },
2406
2407 SchemaRowLayoutVersionExhausted,
2408
2409 JournalMutationRevisionExhausted,
2410
2411 SchemaTransitionBudgetExceeded {
2412 resource: SchemaTransitionBudgetResource,
2413 },
2414
2415 SchemaGeneratedFieldAfterDdlField,
2417
2418 SchemaGeneratedConstraintActivationStale,
2420}
2421
2422pub enum QueryErrorDetail {
2429 NumericOverflow,
2430
2431 NumericNotRepresentable,
2432
2433 UnsupportedSqlFeature {
2434 feature: diagnostic_code::SqlFeatureCode,
2435 },
2436
2437 SqlLowering {
2438 reason: diagnostic_code::SqlLoweringCode,
2439 },
2440
2441 UnsupportedProjection {
2442 reason: diagnostic_code::QueryProjectionCode,
2443 },
2444
2445 UnknownAggregateTargetField,
2446
2447 ResultShapeMismatch {
2448 reason: diagnostic_code::QueryResultShapeCode,
2449 },
2450
2451 QueryReadAdmission {
2452 reason: diagnostic_code::QueryReadAdmissionCode,
2453 },
2454
2455 SqlSurfaceMismatch {
2456 mismatch: diagnostic_code::SqlSurfaceMismatchCode,
2457 },
2458
2459 SqlWriteBoundary {
2460 boundary: diagnostic_code::SqlWriteBoundaryCode,
2461 },
2462
2463 SchemaDdlAdmission {
2464 error: SchemaDdlAdmissionError,
2465 },
2466
2467 StaleSchemaRevision,
2468}
2469
2470impl fmt::Display for QueryErrorDetail {
2471 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2472 f.write_str(COMPACT_QUERY_DIAGNOSTIC_MESSAGE)
2473 }
2474}
2475
2476impl std::error::Error for QueryErrorDetail {}
2477
2478#[derive(Clone, Copy, Debug, Eq, PartialEq)]
2486pub enum SchemaTransitionBudgetResource {
2487 DeletionKeys,
2489 ProjectionEntries,
2491 ProjectionWorkUnits,
2493 SourceRows,
2495 SourceRowBytes,
2497 StagedRawBytes,
2499}
2500
2501#[derive(Clone, Copy, Eq, PartialEq)]
2510pub enum SchemaDdlAdmissionError {
2511 MissingExpectedSchemaVersion,
2512
2513 MissingNextSchemaVersion,
2514
2515 StaleExpectedSchemaVersion,
2516
2517 InvalidExpectedSchemaVersion,
2518
2519 InvalidNextSchemaVersion,
2520
2521 AcceptedSchemaChangeWithoutVersionBump,
2522
2523 EmptyVersionBump,
2524
2525 VersionGap,
2526
2527 VersionRollback,
2528
2529 FingerprintMethodMismatch,
2530
2531 UnsupportedTransitionClass,
2532
2533 PhysicalRunnerMissing,
2534
2535 ValidationFailed,
2536
2537 PublicationRaceLost,
2538
2539 InvalidAddColumnDefault,
2540
2541 InvalidAlterColumnDefault,
2542
2543 RowLayoutVersionExhausted,
2544
2545 GeneratedIndexDropRejected,
2546
2547 SchemaRewriteRequiresMigration,
2548
2549 SchemaTransitionBudgetExceeded {
2550 resource: SchemaTransitionBudgetResource,
2551 },
2552
2553 GeneratedFieldDefaultChangeRejected,
2554
2555 GeneratedFieldNullabilityChangeRejected,
2556}
2557
2558impl fmt::Display for SchemaDdlAdmissionError {
2559 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2560 f.write_str(COMPACT_QUERY_DIAGNOSTIC_MESSAGE)
2561 }
2562}
2563
2564impl std::error::Error for SchemaDdlAdmissionError {}
2565
2566impl fmt::Debug for ErrorDetail {
2567 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2568 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2569 }
2570}
2571
2572impl fmt::Debug for ExecutorErrorDetail {
2573 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2574 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2575 }
2576}
2577
2578impl fmt::Debug for StoreError {
2579 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2580 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2581 }
2582}
2583
2584impl fmt::Debug for QueryErrorDetail {
2585 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2586 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2587 }
2588}
2589
2590impl fmt::Debug for RecoveryErrorDetail {
2591 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2592 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2593 }
2594}
2595
2596impl fmt::Debug for RecoveryFormatMarkerError {
2597 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2598 fmt_compact_diagnostic(
2599 f,
2600 diagnostic_code::DiagnosticCode::RuntimeCorruption,
2601 Some(diagnostic_code::DiagnosticDetail::RuntimeKind {
2602 kind: diagnostic_code::RuntimeErrorKind::Corruption,
2603 }),
2604 )
2605 }
2606}
2607
2608impl fmt::Debug for SchemaDdlAdmissionError {
2609 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2610 fmt_compact_diagnostic(
2611 f,
2612 diagnostic_code::DiagnosticCode::SchemaDdlAdmission,
2613 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2614 reason: self.diagnostic_code(),
2615 }),
2616 )
2617 }
2618}
2619
2620fn fmt_compact_diagnostic(
2621 f: &mut fmt::Formatter<'_>,
2622 code: diagnostic_code::DiagnosticCode,
2623 detail: Option<diagnostic_code::DiagnosticDetail>,
2624) -> fmt::Result {
2625 write!(
2626 f,
2627 "{}",
2628 diagnostic_code::ErrorCode::from_parts(code, detail).raw()
2629 )
2630}
2631
2632impl ErrorDetail {
2633 #[must_use]
2635 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2636 match self {
2637 Self::DiagnosticFacts(detail) => detail.diagnostic.code(),
2638 Self::Executor(error) => error.diagnostic_code(),
2639 Self::Store(error) => error.diagnostic_code(),
2640 Self::Query(error) => error.diagnostic_code(),
2641 Self::Recovery(error) => error.diagnostic_code(),
2642 }
2643 }
2644
2645 #[must_use]
2647 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2648 match self {
2649 Self::DiagnosticFacts(detail) => detail.diagnostic.detail().copied(),
2650 Self::Executor(error) => error.diagnostic_detail(),
2651 Self::Store(error) => error.diagnostic_detail(),
2652 Self::Query(error) => error.diagnostic_detail(),
2653 Self::Recovery(error) => error.diagnostic_detail(),
2654 }
2655 }
2656
2657 #[must_use]
2659 #[cold]
2660 #[inline(never)]
2661 pub fn diagnostic_facts(&self) -> Vec<(diagnostic_code::DiagnosticFactTag, u64)> {
2662 match self {
2663 Self::DiagnosticFacts(detail) => detail.facts.clone(),
2664 Self::Executor(error) => error.diagnostic_facts(),
2665 Self::Query(error) => error.diagnostic_facts(),
2666 Self::Recovery(error) => error.diagnostic_facts(),
2667 Self::Store(_) => Vec::new(),
2668 }
2669 }
2670}
2671
2672impl ExecutorErrorDetail {
2673 #[must_use]
2675 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2676 match self {
2677 Self::MutationRequiredFieldMissing
2678 | Self::MutationDatabaseOwnedFieldExplicit
2679 | Self::MutationBatchEmpty
2680 | Self::MutationBatchTooManyItems
2681 | Self::MutationBatchStagedBytesExceeded
2682 | Self::MutationBatchResultBytesExceeded => {
2683 diagnostic_code::DiagnosticCode::RuntimeUnsupported
2684 }
2685 Self::MutationBatchEntityMismatch | Self::MutationBatchDuplicateKey => {
2686 diagnostic_code::DiagnosticCode::RuntimeConflict
2687 }
2688 Self::MutationManagedTimestampRegression => {
2689 diagnostic_code::DiagnosticCode::RuntimeInvariantViolation
2690 }
2691 Self::AcceptedRowConstraintProgramCorrupt => {
2692 diagnostic_code::DiagnosticCode::RuntimeCorruption
2693 }
2694 }
2695 }
2696
2697 #[must_use]
2699 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2700 match self {
2701 Self::MutationRequiredFieldMissing => {
2702 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2703 boundary: diagnostic_code::RuntimeBoundaryCode::MutationRequiredFieldMissing,
2704 })
2705 }
2706 Self::MutationDatabaseOwnedFieldExplicit => {
2707 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2708 boundary:
2709 diagnostic_code::RuntimeBoundaryCode::MutationDatabaseOwnedFieldExplicit,
2710 })
2711 }
2712 Self::MutationBatchEmpty => Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2713 boundary: diagnostic_code::RuntimeBoundaryCode::MutationBatchEmpty,
2714 }),
2715 Self::MutationBatchTooManyItems => {
2716 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2717 boundary: diagnostic_code::RuntimeBoundaryCode::MutationBatchTooManyItems,
2718 })
2719 }
2720 Self::MutationBatchStagedBytesExceeded => {
2721 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2722 boundary:
2723 diagnostic_code::RuntimeBoundaryCode::MutationBatchStagedBytesExceeded,
2724 })
2725 }
2726 Self::MutationBatchResultBytesExceeded => {
2727 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2728 boundary:
2729 diagnostic_code::RuntimeBoundaryCode::MutationBatchResultBytesExceeded,
2730 })
2731 }
2732 Self::MutationBatchEntityMismatch => {
2733 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2734 boundary: diagnostic_code::RuntimeBoundaryCode::MutationBatchEntityMismatch,
2735 })
2736 }
2737 Self::MutationBatchDuplicateKey => {
2738 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2739 boundary: diagnostic_code::RuntimeBoundaryCode::MutationBatchDuplicateKey,
2740 })
2741 }
2742 Self::MutationManagedTimestampRegression => {
2743 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2744 boundary:
2745 diagnostic_code::RuntimeBoundaryCode::MutationManagedTimestampRegression,
2746 })
2747 }
2748 Self::AcceptedRowConstraintProgramCorrupt => {
2749 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2750 boundary:
2751 diagnostic_code::RuntimeBoundaryCode::AcceptedRowConstraintProgramCorrupt,
2752 })
2753 }
2754 }
2755 }
2756
2757 #[must_use]
2759 #[cold]
2760 #[inline(never)]
2761 pub const fn diagnostic_facts(&self) -> Vec<(diagnostic_code::DiagnosticFactTag, u64)> {
2762 Vec::new()
2763 }
2764}
2765
2766impl RecoveryErrorDetail {
2767 #[must_use]
2769 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2770 match self {
2771 Self::UnsupportedFormatVersion { .. } => {
2772 diagnostic_code::DiagnosticCode::RuntimeIncompatiblePersistedFormat
2773 }
2774 Self::MalformedFormatMarker { .. } => {
2775 diagnostic_code::DiagnosticCode::RuntimeCorruption
2776 }
2777 }
2778 }
2779
2780 #[must_use]
2782 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2783 let kind = match self {
2784 Self::UnsupportedFormatVersion { .. } => {
2785 diagnostic_code::RuntimeErrorKind::IncompatiblePersistedFormat
2786 }
2787 Self::MalformedFormatMarker { .. } => diagnostic_code::RuntimeErrorKind::Corruption,
2788 };
2789
2790 Some(diagnostic_code::DiagnosticDetail::RuntimeKind { kind })
2791 }
2792
2793 #[must_use]
2795 pub fn diagnostic_facts(&self) -> Vec<(diagnostic_code::DiagnosticFactTag, u64)> {
2796 match self {
2797 Self::UnsupportedFormatVersion { found, required } => {
2798 let mut facts = Vec::with_capacity(usize::from(found.is_some()) + 1);
2799 facts.push((
2800 diagnostic_code::DiagnosticFactTag::ExpectedVersion,
2801 u64::from(*required),
2802 ));
2803 if let Some(found) = found {
2804 facts.push((
2805 diagnostic_code::DiagnosticFactTag::ActualVersion,
2806 u64::from(*found),
2807 ));
2808 }
2809 facts
2810 }
2811 Self::MalformedFormatMarker { reason } => vec![(
2812 diagnostic_code::DiagnosticFactTag::DecodeReason,
2813 reason.diagnostic_decode_reason().raw(),
2814 )],
2815 }
2816 }
2817}
2818
2819impl StoreError {
2820 #[must_use]
2822 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2823 match self {
2824 Self::NotFound => diagnostic_code::DiagnosticCode::StoreNotFound,
2825 Self::Corrupt => diagnostic_code::DiagnosticCode::StoreCorruption,
2826 Self::InvariantViolation => diagnostic_code::DiagnosticCode::StoreInvariantViolation,
2827 Self::SchemaDdlPublicationRaceLost
2828 | Self::SchemaDdlRewriteRequiresMigration
2829 | Self::SchemaRowLayoutVersionExhausted
2830 | Self::SchemaTransitionBudgetExceeded { .. } => {
2831 diagnostic_code::DiagnosticCode::SchemaDdlAdmission
2832 }
2833 Self::JournalMutationRevisionExhausted | Self::SchemaGeneratedFieldAfterDdlField => {
2834 diagnostic_code::DiagnosticCode::RuntimeUnsupported
2835 }
2836 Self::SchemaGeneratedConstraintActivationStale => {
2837 diagnostic_code::DiagnosticCode::RuntimeConflict
2838 }
2839 Self::SchemaMigration { reason } => reason.diagnostic_code(),
2840 }
2841 }
2842
2843 #[must_use]
2845 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2846 match self {
2847 Self::SchemaDdlPublicationRaceLost => {
2848 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2849 reason: diagnostic_code::SchemaDdlAdmissionCode::PublicationRaceLost,
2850 })
2851 }
2852 Self::SchemaDdlRewriteRequiresMigration => {
2853 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2854 reason: diagnostic_code::SchemaDdlAdmissionCode::SchemaRewriteRequiresMigration,
2855 })
2856 }
2857 Self::SchemaMigration { reason } => {
2858 Some(diagnostic_code::DiagnosticDetail::SchemaMigration { reason: *reason })
2859 }
2860 Self::SchemaRowLayoutVersionExhausted => {
2861 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2862 reason: diagnostic_code::SchemaDdlAdmissionCode::RowLayoutVersionExhausted,
2863 })
2864 }
2865 Self::JournalMutationRevisionExhausted => {
2866 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2867 boundary:
2868 diagnostic_code::RuntimeBoundaryCode::JournalMutationRevisionExhausted,
2869 })
2870 }
2871 Self::SchemaTransitionBudgetExceeded { .. } => {
2872 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2873 reason: diagnostic_code::SchemaDdlAdmissionCode::SchemaTransitionBudgetExceeded,
2874 })
2875 }
2876 Self::SchemaGeneratedFieldAfterDdlField => {
2877 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2878 boundary: diagnostic_code::RuntimeBoundaryCode::GeneratedFieldAfterDdlField,
2879 })
2880 }
2881 Self::SchemaGeneratedConstraintActivationStale => {
2882 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2883 boundary:
2884 diagnostic_code::RuntimeBoundaryCode::GeneratedConstraintActivationStale,
2885 })
2886 }
2887 Self::NotFound | Self::Corrupt | Self::InvariantViolation => None,
2888 }
2889 }
2890}
2891
2892impl QueryErrorDetail {
2893 #[must_use]
2895 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2896 match self {
2897 Self::NumericOverflow => diagnostic_code::DiagnosticCode::QueryNumericOverflow,
2898 Self::NumericNotRepresentable => {
2899 diagnostic_code::DiagnosticCode::QueryNumericNotRepresentable
2900 }
2901 Self::UnsupportedSqlFeature { .. } => {
2902 diagnostic_code::DiagnosticCode::QueryUnsupportedSqlFeature
2903 }
2904 Self::SqlLowering { .. } => diagnostic_code::DiagnosticCode::QueryUnsupportedSqlFeature,
2905 Self::UnsupportedProjection { .. } => {
2906 diagnostic_code::DiagnosticCode::QueryUnsupportedProjection
2907 }
2908 Self::UnknownAggregateTargetField => {
2909 diagnostic_code::DiagnosticCode::QueryUnknownAggregateTargetField
2910 }
2911 Self::ResultShapeMismatch { .. } => {
2912 diagnostic_code::DiagnosticCode::QueryResultShapeMismatch
2913 }
2914 Self::QueryReadAdmission { .. } => diagnostic_code::DiagnosticCode::QueryReadAdmission,
2915 Self::SqlSurfaceMismatch { .. } => {
2916 diagnostic_code::DiagnosticCode::QuerySqlSurfaceMismatch
2917 }
2918 Self::SqlWriteBoundary { .. } => diagnostic_code::DiagnosticCode::QuerySqlWriteBoundary,
2919 Self::SchemaDdlAdmission { .. } => diagnostic_code::DiagnosticCode::SchemaDdlAdmission,
2920 Self::StaleSchemaRevision => diagnostic_code::DiagnosticCode::RuntimeConflict,
2921 }
2922 }
2923
2924 #[must_use]
2926 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2927 match self {
2928 Self::UnsupportedSqlFeature { feature } => {
2929 Some(diagnostic_code::DiagnosticDetail::UnsupportedSqlFeature { feature: *feature })
2930 }
2931 Self::SqlLowering { reason } => {
2932 Some(diagnostic_code::DiagnosticDetail::SqlLowering { reason: *reason })
2933 }
2934 Self::UnsupportedProjection { reason } => {
2935 Some(diagnostic_code::DiagnosticDetail::QueryProjection { reason: *reason })
2936 }
2937 Self::ResultShapeMismatch { reason } => {
2938 Some(diagnostic_code::DiagnosticDetail::QueryResultShape { reason: *reason })
2939 }
2940 Self::QueryReadAdmission { reason } => {
2941 Some(diagnostic_code::DiagnosticDetail::QueryReadAdmission { reason: *reason })
2942 }
2943 Self::SqlSurfaceMismatch { mismatch } => {
2944 Some(diagnostic_code::DiagnosticDetail::SqlSurfaceMismatch {
2945 mismatch: *mismatch,
2946 })
2947 }
2948 Self::SqlWriteBoundary { boundary } => {
2949 Some(diagnostic_code::DiagnosticDetail::SqlWriteBoundary {
2950 boundary: *boundary,
2951 })
2952 }
2953 Self::SchemaDdlAdmission { error } => {
2954 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2955 reason: error.diagnostic_code(),
2956 })
2957 }
2958 Self::NumericOverflow
2959 | Self::NumericNotRepresentable
2960 | Self::UnknownAggregateTargetField
2961 | Self::StaleSchemaRevision => None,
2962 }
2963 }
2964
2965 #[must_use]
2967 #[cold]
2968 #[inline(never)]
2969 pub const fn diagnostic_facts(&self) -> Vec<(diagnostic_code::DiagnosticFactTag, u64)> {
2970 Vec::new()
2971 }
2972}
2973
2974impl SchemaDdlAdmissionError {
2975 #[must_use]
2977 pub const fn diagnostic_code(&self) -> diagnostic_code::SchemaDdlAdmissionCode {
2978 match self {
2979 Self::MissingExpectedSchemaVersion => {
2980 diagnostic_code::SchemaDdlAdmissionCode::MissingExpectedSchemaVersion
2981 }
2982 Self::MissingNextSchemaVersion => {
2983 diagnostic_code::SchemaDdlAdmissionCode::MissingNextSchemaVersion
2984 }
2985 Self::StaleExpectedSchemaVersion => {
2986 diagnostic_code::SchemaDdlAdmissionCode::StaleExpectedSchemaVersion
2987 }
2988 Self::InvalidExpectedSchemaVersion => {
2989 diagnostic_code::SchemaDdlAdmissionCode::InvalidExpectedSchemaVersion
2990 }
2991 Self::InvalidNextSchemaVersion => {
2992 diagnostic_code::SchemaDdlAdmissionCode::InvalidNextSchemaVersion
2993 }
2994 Self::AcceptedSchemaChangeWithoutVersionBump => {
2995 diagnostic_code::SchemaDdlAdmissionCode::AcceptedSchemaChangeWithoutVersionBump
2996 }
2997 Self::EmptyVersionBump => diagnostic_code::SchemaDdlAdmissionCode::EmptyVersionBump,
2998 Self::VersionGap => diagnostic_code::SchemaDdlAdmissionCode::VersionGap,
2999 Self::VersionRollback => diagnostic_code::SchemaDdlAdmissionCode::VersionRollback,
3000 Self::FingerprintMethodMismatch => {
3001 diagnostic_code::SchemaDdlAdmissionCode::FingerprintMethodMismatch
3002 }
3003 Self::UnsupportedTransitionClass => {
3004 diagnostic_code::SchemaDdlAdmissionCode::UnsupportedTransitionClass
3005 }
3006 Self::PhysicalRunnerMissing => {
3007 diagnostic_code::SchemaDdlAdmissionCode::PhysicalRunnerMissing
3008 }
3009 Self::ValidationFailed => diagnostic_code::SchemaDdlAdmissionCode::ValidationFailed,
3010 Self::PublicationRaceLost => {
3011 diagnostic_code::SchemaDdlAdmissionCode::PublicationRaceLost
3012 }
3013 Self::InvalidAddColumnDefault => {
3014 diagnostic_code::SchemaDdlAdmissionCode::InvalidAddColumnDefault
3015 }
3016 Self::InvalidAlterColumnDefault => {
3017 diagnostic_code::SchemaDdlAdmissionCode::InvalidAlterColumnDefault
3018 }
3019 Self::GeneratedIndexDropRejected => {
3020 diagnostic_code::SchemaDdlAdmissionCode::GeneratedIndexDropRejected
3021 }
3022 Self::SchemaRewriteRequiresMigration => {
3023 diagnostic_code::SchemaDdlAdmissionCode::SchemaRewriteRequiresMigration
3024 }
3025 Self::SchemaTransitionBudgetExceeded { .. } => {
3026 diagnostic_code::SchemaDdlAdmissionCode::SchemaTransitionBudgetExceeded
3027 }
3028 Self::GeneratedFieldDefaultChangeRejected => {
3029 diagnostic_code::SchemaDdlAdmissionCode::GeneratedFieldDefaultChangeRejected
3030 }
3031 Self::GeneratedFieldNullabilityChangeRejected => {
3032 diagnostic_code::SchemaDdlAdmissionCode::GeneratedFieldNullabilityChangeRejected
3033 }
3034 Self::RowLayoutVersionExhausted => {
3035 diagnostic_code::SchemaDdlAdmissionCode::RowLayoutVersionExhausted
3036 }
3037 }
3038 }
3039}
3040
3041#[repr(u8)]
3048#[derive(Clone, Copy, Eq, PartialEq)]
3049pub enum ErrorClass {
3050 Corruption,
3051 IncompatiblePersistedFormat,
3052 NotFound,
3053 Internal,
3054 Conflict,
3055 Unsupported,
3056 InvariantViolation,
3057}
3058
3059impl ErrorClass {
3060 #[must_use]
3062 pub const fn diagnostic_code(self, origin: ErrorOrigin) -> diagnostic_code::DiagnosticCode {
3063 match self {
3064 Self::Corruption if matches!(origin, ErrorOrigin::Store) => {
3065 diagnostic_code::DiagnosticCode::StoreCorruption
3066 }
3067 Self::Corruption => diagnostic_code::DiagnosticCode::RuntimeCorruption,
3068 Self::IncompatiblePersistedFormat => {
3069 diagnostic_code::DiagnosticCode::RuntimeIncompatiblePersistedFormat
3070 }
3071 Self::NotFound if matches!(origin, ErrorOrigin::Store) => {
3072 diagnostic_code::DiagnosticCode::StoreNotFound
3073 }
3074 Self::NotFound => diagnostic_code::DiagnosticCode::RuntimeNotFound,
3075 Self::Internal => diagnostic_code::DiagnosticCode::RuntimeInternal,
3076 Self::Conflict => diagnostic_code::DiagnosticCode::RuntimeConflict,
3077 Self::Unsupported if matches!(origin, ErrorOrigin::Cursor) => {
3078 diagnostic_code::DiagnosticCode::QueryInvalidContinuationCursor
3079 }
3080 Self::Unsupported => diagnostic_code::DiagnosticCode::RuntimeUnsupported,
3081 Self::InvariantViolation if matches!(origin, ErrorOrigin::Store) => {
3082 diagnostic_code::DiagnosticCode::StoreInvariantViolation
3083 }
3084 Self::InvariantViolation => diagnostic_code::DiagnosticCode::RuntimeInvariantViolation,
3085 }
3086 }
3087}
3088
3089impl fmt::Debug for ErrorClass {
3090 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3091 write!(f, "{}", *self as u8)
3092 }
3093}
3094
3095#[repr(u8)]
3102#[derive(Clone, Copy, Eq, PartialEq)]
3103pub enum ErrorOrigin {
3104 Serialize,
3105 Store,
3106 Index,
3107 Identity,
3108 Query,
3109 Planner,
3110 Cursor,
3111 Recovery,
3112 Response,
3113 Executor,
3114 Interface,
3115}
3116
3117impl ErrorOrigin {
3118 #[must_use]
3120 pub const fn diagnostic_origin(self) -> diagnostic_code::ErrorOrigin {
3121 match self {
3122 Self::Serialize => diagnostic_code::ErrorOrigin::Serialize,
3123 Self::Store => diagnostic_code::ErrorOrigin::Store,
3124 Self::Index => diagnostic_code::ErrorOrigin::Index,
3125 Self::Identity => diagnostic_code::ErrorOrigin::Identity,
3126 Self::Query => diagnostic_code::ErrorOrigin::Query,
3127 Self::Planner => diagnostic_code::ErrorOrigin::Planner,
3128 Self::Cursor => diagnostic_code::ErrorOrigin::Cursor,
3129 Self::Recovery => diagnostic_code::ErrorOrigin::Recovery,
3130 Self::Response => diagnostic_code::ErrorOrigin::Response,
3131 Self::Executor => diagnostic_code::ErrorOrigin::Executor,
3132 Self::Interface => diagnostic_code::ErrorOrigin::Interface,
3133 }
3134 }
3135}
3136
3137impl fmt::Debug for ErrorOrigin {
3138 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3139 write!(f, "{}", *self as u8)
3140 }
3141}