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