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 pub(crate) fn persisted_row_size_limit_exceeded(actual_length: usize, limit: usize) -> Self {
1225 Self::with_diagnostic_facts(
1226 ErrorClass::Unsupported,
1227 ErrorOrigin::Serialize,
1228 None,
1229 vec![
1230 (
1231 diagnostic_code::DiagnosticFactTag::ActualLength,
1232 actual_length as u64,
1233 ),
1234 (diagnostic_code::DiagnosticFactTag::Limit, limit as u64),
1235 ],
1236 )
1237 }
1238
1239 #[cold]
1241 #[inline(never)]
1242 pub(crate) fn store_corruption() -> Self {
1243 Self::new(ErrorClass::Corruption, ErrorOrigin::Store)
1244 }
1245
1246 pub(crate) fn commit_corruption() -> Self {
1248 Self::store_corruption()
1249 }
1250
1251 pub(crate) fn commit_component_corruption() -> Self {
1253 Self::commit_corruption()
1254 }
1255
1256 pub(crate) fn commit_id_generation_failed() -> Self {
1258 Self::store_internal()
1259 }
1260
1261 pub(crate) fn commit_marker_payload_exceeds_u32_length_limit() -> Self {
1263 Self::store_unsupported()
1264 }
1265
1266 pub(crate) fn commit_component_length_invalid(actual_length: usize, limit: usize) -> Self {
1268 Self::with_diagnostic_facts(
1269 ErrorClass::Corruption,
1270 ErrorOrigin::Store,
1271 None,
1272 vec![
1273 (
1274 diagnostic_code::DiagnosticFactTag::ComponentKind,
1275 diagnostic_code::DiagnosticComponentKind::CommitDataKey.raw(),
1276 ),
1277 (
1278 diagnostic_code::DiagnosticFactTag::ActualLength,
1279 actual_length as u64,
1280 ),
1281 (diagnostic_code::DiagnosticFactTag::Limit, limit as u64),
1282 ],
1283 )
1284 }
1285
1286 pub(crate) fn commit_marker_exceeds_max_size() -> Self {
1288 Self::commit_corruption()
1289 }
1290
1291 pub(crate) fn commit_control_slot_exceeds_max_size() -> Self {
1293 Self::store_unsupported()
1294 }
1295
1296 pub(crate) fn commit_control_slot_marker_bytes_exceed_u32_length_limit() -> Self {
1298 Self::store_unsupported()
1299 }
1300
1301 #[cold]
1303 #[inline(never)]
1304 pub(crate) fn index_corruption() -> Self {
1305 Self::new(ErrorClass::Corruption, ErrorOrigin::Index)
1306 }
1307
1308 pub(crate) fn index_unique_validation_corruption() -> Self {
1310 Self::index_plan_index_corruption()
1311 }
1312
1313 pub(crate) fn structural_index_entry_corruption() -> Self {
1315 Self::index_plan_index_corruption()
1316 }
1317
1318 pub(crate) fn index_unique_validation_entity_key_required() -> Self {
1320 Self::index_invariant()
1321 }
1322
1323 pub(crate) fn index_unique_validation_row_deserialize_failed() -> Self {
1325 Self::index_plan_serialize_corruption()
1326 }
1327
1328 pub(crate) fn index_unique_validation_primary_key_decode_failed() -> Self {
1330 Self::index_plan_serialize_corruption()
1331 }
1332
1333 pub(crate) fn index_unique_validation_key_rebuild_failed() -> Self {
1335 Self::index_plan_serialize_corruption()
1336 }
1337
1338 pub(crate) fn index_unique_validation_row_required() -> Self {
1340 Self::index_plan_store_corruption()
1341 }
1342
1343 pub(crate) fn index_only_predicate_component_required() -> Self {
1345 Self::index_invariant()
1346 }
1347
1348 pub(crate) fn index_scan_continuation_anchor_within_envelope_required() -> Self {
1350 Self::index_invariant()
1351 }
1352
1353 pub(crate) fn index_scan_continuation_advancement_required() -> Self {
1355 Self::index_invariant()
1356 }
1357
1358 pub(crate) fn index_entry_decode_failed() -> Self {
1360 Self::index_corruption()
1361 }
1362
1363 pub(crate) fn serialize_corruption() -> Self {
1365 Self::new(ErrorClass::Corruption, ErrorOrigin::Serialize)
1366 }
1367
1368 pub(crate) fn persisted_row_decode_corruption() -> Self {
1370 Self::serialize_corruption()
1371 }
1372
1373 pub(crate) fn persisted_row_layout_outside_accepted_window(
1375 row_layout: u32,
1376 history_floor: u32,
1377 current_layout: u32,
1378 ) -> Self {
1379 Self::with_diagnostic_facts(
1380 ErrorClass::Corruption,
1381 ErrorOrigin::Serialize,
1382 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
1383 boundary:
1384 diagnostic_code::RuntimeBoundaryCode::PersistedRowLayoutOutsideAcceptedWindow,
1385 }),
1386 vec![
1387 (
1388 diagnostic_code::DiagnosticFactTag::RowLayout,
1389 u64::from(row_layout),
1390 ),
1391 (
1392 diagnostic_code::DiagnosticFactTag::HistoryFloor,
1393 u64::from(history_floor),
1394 ),
1395 (
1396 diagnostic_code::DiagnosticFactTag::CurrentLayout,
1397 u64::from(current_layout),
1398 ),
1399 ],
1400 )
1401 }
1402
1403 pub(crate) fn persisted_row_slot_count_mismatch(
1405 row_layout: u32,
1406 expected_slot_count: usize,
1407 actual_slot_count: usize,
1408 ) -> Self {
1409 Self::with_diagnostic_facts(
1410 ErrorClass::Corruption,
1411 ErrorOrigin::Serialize,
1412 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
1413 boundary: diagnostic_code::RuntimeBoundaryCode::PersistedRowSlotCountMismatch,
1414 }),
1415 vec![
1416 (
1417 diagnostic_code::DiagnosticFactTag::RowLayout,
1418 u64::from(row_layout),
1419 ),
1420 (
1421 diagnostic_code::DiagnosticFactTag::ExpectedSlotCount,
1422 expected_slot_count as u64,
1423 ),
1424 (
1425 diagnostic_code::DiagnosticFactTag::ActualSlotCount,
1426 actual_slot_count as u64,
1427 ),
1428 ],
1429 )
1430 }
1431
1432 pub(crate) fn persisted_row_key_mismatch() -> Self {
1434 Self::store_corruption()
1435 }
1436
1437 pub(crate) fn with_relation_identity(self, entity_tag: u64, relation_id: u32) -> Self {
1439 if self.diagnostic().error_code() != diagnostic_code::ErrorCode::RUNTIME_INTERNAL {
1440 return self;
1441 }
1442 let mut facts = vec![
1443 (diagnostic_code::DiagnosticFactTag::EntityTag, entity_tag),
1444 (
1445 diagnostic_code::DiagnosticFactTag::RelationId,
1446 u64::from(relation_id),
1447 ),
1448 ];
1449 facts.extend(self.diagnostic_facts());
1450 Self::with_diagnostic_facts(self.class, self.origin, None, facts)
1451 }
1452
1453 pub(crate) fn relation_target_primary_key_arity_mismatch(
1455 expected_arity: usize,
1456 actual_arity: usize,
1457 ) -> Self {
1458 Self::with_diagnostic_facts(
1459 ErrorClass::Internal,
1460 ErrorOrigin::Executor,
1461 None,
1462 vec![
1463 (
1464 diagnostic_code::DiagnosticFactTag::ComponentKind,
1465 diagnostic_code::DiagnosticComponentKind::RelationTargetPrimaryKey.raw(),
1466 ),
1467 (
1468 diagnostic_code::DiagnosticFactTag::ExpectedArity,
1469 expected_arity as u64,
1470 ),
1471 (
1472 diagnostic_code::DiagnosticFactTag::ActualArity,
1473 actual_arity as u64,
1474 ),
1475 ],
1476 )
1477 }
1478
1479 pub(crate) fn bytes_covering_component_payload_empty() -> Self {
1481 Self::index_corruption()
1482 }
1483
1484 pub(crate) fn bytes_covering_bool_payload_truncated() -> Self {
1486 Self::index_corruption()
1487 }
1488
1489 pub(crate) fn bytes_covering_component_payload_invalid_length() -> Self {
1491 Self::index_corruption()
1492 }
1493
1494 pub(crate) fn bytes_covering_bool_payload_invalid_value() -> Self {
1496 Self::index_corruption()
1497 }
1498
1499 pub(crate) fn bytes_covering_text_payload_invalid_terminator() -> Self {
1501 Self::index_corruption()
1502 }
1503
1504 pub(crate) fn bytes_covering_text_payload_trailing_bytes() -> Self {
1506 Self::index_corruption()
1507 }
1508
1509 pub(crate) fn bytes_covering_text_payload_invalid_utf8() -> Self {
1511 Self::index_corruption()
1512 }
1513
1514 pub(crate) fn bytes_covering_text_payload_invalid_escape_byte() -> Self {
1516 Self::index_corruption()
1517 }
1518
1519 pub(crate) fn bytes_covering_text_payload_missing_terminator() -> Self {
1521 Self::index_corruption()
1522 }
1523
1524 pub(crate) fn identity_corruption() -> Self {
1526 Self::new(ErrorClass::Corruption, ErrorOrigin::Identity)
1527 }
1528
1529 pub(crate) fn identity_state_corruption() -> Self {
1531 Self::identity_corruption()
1532 }
1533
1534 pub(crate) fn identity_state_conflict() -> Self {
1536 Self::new(ErrorClass::Conflict, ErrorOrigin::Identity)
1537 }
1538
1539 pub(crate) fn identity_state_capacity_exhausted() -> Self {
1541 Self::new(ErrorClass::Unsupported, ErrorOrigin::Identity)
1542 }
1543
1544 pub(crate) fn identity_exhausted() -> Self {
1546 Self::new(ErrorClass::Unsupported, ErrorOrigin::Identity)
1547 }
1548
1549 pub(crate) fn identity_candidate_count_exhausted() -> Self {
1551 Self::new(ErrorClass::Unsupported, ErrorOrigin::Identity)
1552 }
1553
1554 #[cold]
1556 #[inline(never)]
1557 pub(crate) fn store_unsupported() -> Self {
1558 Self::new(ErrorClass::Unsupported, ErrorOrigin::Store)
1559 }
1560
1561 pub(crate) fn schema_application_conflict() -> Self {
1563 Self::new(ErrorClass::Conflict, ErrorOrigin::Store)
1564 }
1565
1566 pub(crate) fn schema_migration(reason: diagnostic_code::SchemaMigrationCode) -> Self {
1568 let class = match reason.diagnostic_code() {
1569 diagnostic_code::DiagnosticCode::RuntimeConflict => ErrorClass::Conflict,
1570 diagnostic_code::DiagnosticCode::RuntimeCorruption => ErrorClass::Corruption,
1571 diagnostic_code::DiagnosticCode::RuntimeUnsupported => ErrorClass::Unsupported,
1572 _ => ErrorClass::Internal,
1573 };
1574 Self {
1575 class,
1576 origin: ErrorOrigin::Store,
1577 detail: Some(ErrorDetail::Store(StoreError::SchemaMigration { reason })),
1578 }
1579 }
1580
1581 pub(crate) fn schema_ddl_publication_race_lost() -> Self {
1583 Self {
1584 class: ErrorClass::Unsupported,
1585 origin: ErrorOrigin::Store,
1586 detail: Some(ErrorDetail::Store(StoreError::SchemaDdlPublicationRaceLost)),
1587 }
1588 }
1589
1590 #[cfg(feature = "sql")]
1592 pub(crate) fn schema_ddl_rewrite_requires_migration() -> Self {
1593 Self {
1594 class: ErrorClass::Unsupported,
1595 origin: ErrorOrigin::Store,
1596 detail: Some(ErrorDetail::Store(
1597 StoreError::SchemaDdlRewriteRequiresMigration,
1598 )),
1599 }
1600 }
1601
1602 pub(crate) fn journal_mutation_revision_exhausted() -> Self {
1604 Self {
1605 class: ErrorClass::Unsupported,
1606 origin: ErrorOrigin::Store,
1607 detail: Some(ErrorDetail::Store(
1608 StoreError::JournalMutationRevisionExhausted,
1609 )),
1610 }
1611 }
1612
1613 pub(crate) fn schema_transition_budget_exceeded(
1615 resource: SchemaTransitionBudgetResource,
1616 ) -> Self {
1617 Self {
1618 class: ErrorClass::Unsupported,
1619 origin: ErrorOrigin::Store,
1620 detail: Some(ErrorDetail::Store(
1621 StoreError::SchemaTransitionBudgetExceeded { resource },
1622 )),
1623 }
1624 }
1625
1626 pub(crate) fn index_unsupported() -> Self {
1628 Self::new(ErrorClass::Unsupported, ErrorOrigin::Index)
1629 }
1630
1631 pub(crate) fn index_key_exceeds_max_size_at(
1633 entity_tag: u64,
1634 physical_generation: u64,
1635 actual_length: usize,
1636 limit: usize,
1637 ) -> Self {
1638 Self::with_diagnostic_facts(
1639 ErrorClass::Unsupported,
1640 ErrorOrigin::Index,
1641 None,
1642 vec![
1643 (diagnostic_code::DiagnosticFactTag::EntityTag, entity_tag),
1644 (
1645 diagnostic_code::DiagnosticFactTag::PhysicalGeneration,
1646 physical_generation,
1647 ),
1648 (
1649 diagnostic_code::DiagnosticFactTag::ComponentKind,
1650 diagnostic_code::DiagnosticComponentKind::IndexKey.raw(),
1651 ),
1652 (
1653 diagnostic_code::DiagnosticFactTag::ActualLength,
1654 actual_length as u64,
1655 ),
1656 (diagnostic_code::DiagnosticFactTag::Limit, limit as u64),
1657 ],
1658 )
1659 }
1660
1661 pub(crate) fn index_component_exceeds_max_size_at(
1663 entity_tag: u64,
1664 physical_generation: u64,
1665 component_index: usize,
1666 actual_length: usize,
1667 limit: usize,
1668 ) -> Self {
1669 Self::with_diagnostic_facts(
1670 ErrorClass::Unsupported,
1671 ErrorOrigin::Index,
1672 None,
1673 vec![
1674 (diagnostic_code::DiagnosticFactTag::EntityTag, entity_tag),
1675 (
1676 diagnostic_code::DiagnosticFactTag::PhysicalGeneration,
1677 physical_generation,
1678 ),
1679 (
1680 diagnostic_code::DiagnosticFactTag::ComponentIndex,
1681 component_index as u64,
1682 ),
1683 (
1684 diagnostic_code::DiagnosticFactTag::ComponentKind,
1685 diagnostic_code::DiagnosticComponentKind::IndexKeyComponent.raw(),
1686 ),
1687 (
1688 diagnostic_code::DiagnosticFactTag::ActualLength,
1689 actual_length as u64,
1690 ),
1691 (diagnostic_code::DiagnosticFactTag::Limit, limit as u64),
1692 ],
1693 )
1694 }
1695
1696 pub(crate) fn index_component_exceeds_max_size() -> Self {
1699 Self::index_unsupported()
1700 }
1701
1702 pub(crate) fn serialize_unsupported() -> Self {
1704 Self::new(ErrorClass::Unsupported, ErrorOrigin::Serialize)
1705 }
1706
1707 pub(crate) fn cursor_invalid_continuation() -> Self {
1709 Self::new(ErrorClass::Unsupported, ErrorOrigin::Cursor)
1710 }
1711
1712 pub(crate) fn serialize_incompatible_persisted_format() -> Self {
1714 Self::new(
1715 ErrorClass::IncompatiblePersistedFormat,
1716 ErrorOrigin::Serialize,
1717 )
1718 }
1719
1720 #[cfg(feature = "sql")]
1723 pub(crate) fn query_unsupported_sql_feature(feature: diagnostic_code::SqlFeatureCode) -> Self {
1724 Self {
1725 class: ErrorClass::Unsupported,
1726 origin: ErrorOrigin::Query,
1727 detail: Some(ErrorDetail::Query(
1728 QueryErrorDetail::UnsupportedSqlFeature { feature },
1729 )),
1730 }
1731 }
1732
1733 #[cfg(feature = "sql")]
1736 pub(crate) fn query_sql_lowering(reason: diagnostic_code::SqlLoweringCode) -> Self {
1737 Self {
1738 class: ErrorClass::Unsupported,
1739 origin: ErrorOrigin::Query,
1740 detail: Some(ErrorDetail::Query(QueryErrorDetail::SqlLowering { reason })),
1741 }
1742 }
1743
1744 #[cfg(feature = "sql")]
1746 pub(crate) fn query_sql_lowering_with_facts(
1747 reason: diagnostic_code::SqlLoweringCode,
1748 facts: Vec<(diagnostic_code::DiagnosticFactTag, u64)>,
1749 ) -> Self {
1750 Self::with_diagnostic_facts(
1751 ErrorClass::Unsupported,
1752 ErrorOrigin::Query,
1753 Some(diagnostic_code::DiagnosticDetail::SqlLowering { reason }),
1754 facts,
1755 )
1756 }
1757
1758 pub(crate) fn query_unsupported_projection(
1761 reason: diagnostic_code::QueryProjectionCode,
1762 ) -> Self {
1763 Self {
1764 class: ErrorClass::Unsupported,
1765 origin: ErrorOrigin::Query,
1766 detail: Some(ErrorDetail::Query(
1767 QueryErrorDetail::UnsupportedProjection { reason },
1768 )),
1769 }
1770 }
1771
1772 #[cfg(feature = "sql")]
1775 pub(crate) fn query_sql_surface_mismatch(
1776 mismatch: diagnostic_code::SqlSurfaceMismatchCode,
1777 ) -> Self {
1778 Self {
1779 class: ErrorClass::Unsupported,
1780 origin: ErrorOrigin::Query,
1781 detail: Some(ErrorDetail::Query(QueryErrorDetail::SqlSurfaceMismatch {
1782 mismatch,
1783 })),
1784 }
1785 }
1786
1787 pub(crate) fn query_sql_write_boundary(
1789 boundary: diagnostic_code::SqlWriteBoundaryCode,
1790 ) -> Self {
1791 Self {
1792 class: ErrorClass::Unsupported,
1793 origin: ErrorOrigin::Query,
1794 detail: Some(ErrorDetail::Query(QueryErrorDetail::SqlWriteBoundary {
1795 boundary,
1796 })),
1797 }
1798 }
1799
1800 pub(crate) fn query_sql_write_boundary_with_facts(
1802 boundary: diagnostic_code::SqlWriteBoundaryCode,
1803 facts: Vec<(diagnostic_code::DiagnosticFactTag, u64)>,
1804 ) -> Self {
1805 Self::with_diagnostic_facts(
1806 ErrorClass::Unsupported,
1807 ErrorOrigin::Query,
1808 Some(diagnostic_code::DiagnosticDetail::SqlWriteBoundary { boundary }),
1809 facts,
1810 )
1811 }
1812
1813 pub fn store_not_found(_key: impl Sized) -> Self {
1814 Self {
1815 class: ErrorClass::NotFound,
1816 origin: ErrorOrigin::Store,
1817 detail: Some(ErrorDetail::Store(StoreError::NotFound)),
1818 }
1819 }
1820
1821 pub fn unsupported_entity_path(_path: impl Sized) -> Self {
1823 Self::store_unsupported()
1824 }
1825
1826 #[cold]
1828 #[inline(never)]
1829 pub(crate) fn index_plan_corruption(origin: ErrorOrigin) -> Self {
1830 Self::new(ErrorClass::Corruption, origin)
1831 }
1832
1833 #[cold]
1835 #[inline(never)]
1836 pub(crate) fn index_plan_index_corruption() -> Self {
1837 Self::index_plan_corruption(ErrorOrigin::Index)
1838 }
1839
1840 #[cold]
1842 #[inline(never)]
1843 pub(crate) fn index_plan_store_corruption() -> Self {
1844 Self::index_plan_corruption(ErrorOrigin::Store)
1845 }
1846
1847 #[cold]
1849 #[inline(never)]
1850 pub(crate) fn index_plan_serialize_corruption() -> Self {
1851 Self::index_plan_corruption(ErrorOrigin::Serialize)
1852 }
1853
1854 #[cfg(test)]
1856 pub(crate) fn index_plan_invariant(origin: ErrorOrigin) -> Self {
1857 Self::new(ErrorClass::InvariantViolation, origin)
1858 }
1859
1860 #[cfg(test)]
1862 pub(crate) fn index_plan_store_invariant() -> Self {
1863 Self::index_plan_invariant(ErrorOrigin::Store)
1864 }
1865
1866 pub(crate) fn index_conflict() -> Self {
1872 Self::new(ErrorClass::Conflict, ErrorOrigin::Index)
1873 }
1874}
1875
1876impl From<diagnostic_code::QueryReadAdmissionCode> for InternalError {
1877 fn from(reason: diagnostic_code::QueryReadAdmissionCode) -> Self {
1878 Self {
1879 class: ErrorClass::Unsupported,
1880 origin: ErrorOrigin::Query,
1881 detail: Some(ErrorDetail::Query(QueryErrorDetail::QueryReadAdmission {
1882 reason,
1883 })),
1884 }
1885 }
1886}
1887
1888impl fmt::Debug for InternalError {
1889 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1890 fmt_compact_diagnostic(
1891 f,
1892 self.diagnostic_code(),
1893 self.detail
1894 .as_ref()
1895 .and_then(ErrorDetail::diagnostic_detail),
1896 )
1897 }
1898}
1899
1900impl fmt::Display for InternalError {
1901 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1902 f.write_str(self.message())
1903 }
1904}
1905
1906impl std::error::Error for InternalError {}
1907
1908#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, serde::Serialize)]
1917pub enum ConstraintValuePathComponent {
1918 RootField { field_id: u32 },
1920
1921 RecordMember {
1923 composite_type_id: u32,
1924 member_id: u32,
1925 },
1926
1927 TupleElement {
1929 composite_type_id: u32,
1930 ordinal: u32,
1931 },
1932
1933 Newtype { composite_type_id: u32 },
1935
1936 EnumVariant { enum_type_id: u32, variant_id: u32 },
1938
1939 ListElement { index: u32 },
1941
1942 SetElement { index: u32 },
1944
1945 MapEntryKey { index: u32 },
1947
1948 MapEntryValue { index: u32 },
1950}
1951
1952impl fmt::Display for ConstraintValuePathComponent {
1953 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1954 match self {
1955 Self::RootField { field_id } => write!(f, "field#{field_id}"),
1956 Self::RecordMember {
1957 composite_type_id,
1958 member_id,
1959 } => write!(f, "record#{composite_type_id}.member#{member_id}"),
1960 Self::TupleElement {
1961 composite_type_id,
1962 ordinal,
1963 } => write!(f, "tuple#{composite_type_id}[{ordinal}]"),
1964 Self::Newtype { composite_type_id } => write!(f, "newtype#{composite_type_id}"),
1965 Self::EnumVariant {
1966 enum_type_id,
1967 variant_id,
1968 } => write!(f, "enum#{enum_type_id}.variant#{variant_id}"),
1969 Self::ListElement { index } => write!(f, "list[{index}]"),
1970 Self::SetElement { index } => write!(f, "set[{index}]"),
1971 Self::MapEntryKey { index } => write!(f, "map[{index}].key"),
1972 Self::MapEntryValue { index } => write!(f, "map[{index}].value"),
1973 }
1974 }
1975}
1976
1977#[derive(Clone, Debug, Deserialize, Eq, PartialEq, serde::Serialize)]
1984pub struct ConstraintValuePath {
1985 components: Vec<ConstraintValuePathComponent>,
1986}
1987
1988impl ConstraintValuePath {
1989 #[must_use]
1991 pub(crate) const fn new(components: Vec<ConstraintValuePathComponent>) -> Self {
1992 Self { components }
1993 }
1994
1995 #[must_use]
1997 pub const fn components(&self) -> &[ConstraintValuePathComponent] {
1998 self.components.as_slice()
1999 }
2000}
2001
2002impl fmt::Display for ConstraintValuePath {
2003 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2004 for (ordinal, component) in self.components.iter().enumerate() {
2005 if ordinal != 0 {
2006 f.write_str("/")?;
2007 }
2008 component.fmt(f)?;
2009 }
2010 Ok(())
2011 }
2012}
2013
2014#[derive(Clone, Debug, Deserialize, Eq, PartialEq, serde::Serialize)]
2023pub struct ConstraintValidationFindingOutput {
2024 accepted_schema_fingerprint: [u8; 16],
2025 entity_tag: u64,
2026 constraint_id: u32,
2027 primary_key: Vec<u8>,
2028 field_ids: Vec<u32>,
2029 value_path: Option<ConstraintValuePath>,
2030 error_code: u16,
2031}
2032
2033impl ConstraintValidationFindingOutput {
2034 #[must_use]
2036 pub(crate) const fn new(
2037 accepted_schema_fingerprint: [u8; 16],
2038 entity_tag: u64,
2039 constraint_id: u32,
2040 primary_key: Vec<u8>,
2041 field_ids: Vec<u32>,
2042 value_path: Option<ConstraintValuePath>,
2043 error_code: u16,
2044 ) -> Self {
2045 Self {
2046 accepted_schema_fingerprint,
2047 entity_tag,
2048 constraint_id,
2049 primary_key,
2050 field_ids,
2051 value_path,
2052 error_code,
2053 }
2054 }
2055
2056 #[must_use]
2058 pub const fn accepted_schema_fingerprint(&self) -> [u8; 16] {
2059 self.accepted_schema_fingerprint
2060 }
2061
2062 #[must_use]
2064 pub const fn entity_tag(&self) -> u64 {
2065 self.entity_tag
2066 }
2067
2068 #[must_use]
2070 pub const fn constraint_id(&self) -> u32 {
2071 self.constraint_id
2072 }
2073
2074 #[must_use]
2076 pub const fn primary_key(&self) -> &[u8] {
2077 self.primary_key.as_slice()
2078 }
2079
2080 #[must_use]
2084 pub const fn field_ids(&self) -> &[u32] {
2085 self.field_ids.as_slice()
2086 }
2087
2088 #[must_use]
2090 pub const fn value_path(&self) -> Option<&ConstraintValuePath> {
2091 self.value_path.as_ref()
2092 }
2093
2094 #[must_use]
2096 pub const fn error_code(&self) -> diagnostic_code::ErrorCode {
2097 diagnostic_code::ErrorCode::from_raw(self.error_code)
2098 }
2099
2100 #[must_use]
2102 pub const fn error_class(&self) -> diagnostic_code::ErrorClass {
2103 self.error_code().class()
2104 }
2105}
2106
2107#[derive(Clone)]
2109pub(crate) struct AcceptedConstraintFactContext {
2110 fingerprint_method: u8,
2111 accepted_schema_fingerprint: [u8; 16],
2112 entity_tag: u64,
2113 constraint_id: u32,
2114 constraint_kind: diagnostic_code::DiagnosticConstraintKind,
2115 mutation: Option<MutationDiagnosticContext>,
2116 value_path: Option<ConstraintValuePath>,
2117}
2118
2119impl AcceptedConstraintFactContext {
2120 #[must_use]
2121 pub(crate) fn write_admission(
2122 fingerprint_method: u8,
2123 accepted_schema_fingerprint: [u8; 16],
2124 entity_tag: u64,
2125 constraint_id: u32,
2126 constraint_kind: diagnostic_code::DiagnosticConstraintKind,
2127 mutation: Option<MutationDiagnosticContext>,
2128 value_path: Option<ConstraintValuePath>,
2129 ) -> Self {
2130 debug_assert!(mutation.is_none_or(|context| context.entity_tag() == entity_tag));
2131 Self {
2132 fingerprint_method,
2133 accepted_schema_fingerprint,
2134 entity_tag,
2135 constraint_id,
2136 constraint_kind,
2137 mutation,
2138 value_path,
2139 }
2140 }
2141
2142 fn facts(self) -> Vec<(diagnostic_code::DiagnosticFactTag, u64)> {
2143 let path_len = self
2144 .value_path
2145 .as_ref()
2146 .map_or(0, |path| path.components().len());
2147 let mutation_fact_count = self.mutation.map_or(0, |mutation| {
2148 1 + usize::from(mutation.batch_position.is_some())
2149 });
2150 let mut facts = Vec::with_capacity(7 + mutation_fact_count + path_len);
2151 append_accepted_schema_facts(
2152 &mut facts,
2153 self.fingerprint_method,
2154 self.accepted_schema_fingerprint,
2155 );
2156 facts.push((
2157 diagnostic_code::DiagnosticFactTag::EntityTag,
2158 self.entity_tag,
2159 ));
2160 facts.push((
2161 diagnostic_code::DiagnosticFactTag::ConstraintId,
2162 u64::from(self.constraint_id),
2163 ));
2164 facts.push((
2165 diagnostic_code::DiagnosticFactTag::ConstraintKind,
2166 self.constraint_kind.raw(),
2167 ));
2168 facts.push((
2169 diagnostic_code::DiagnosticFactTag::ConstraintContext,
2170 diagnostic_code::DiagnosticConstraintContext::WriteAdmission.raw(),
2171 ));
2172 if let Some(mutation) = self.mutation {
2173 mutation.append_operation_facts(&mut facts);
2174 }
2175 if let Some(path) = self.value_path {
2176 for component in path.components {
2177 facts.push(constraint_value_path_fact(component));
2178 }
2179 }
2180 debug_assert!(facts.len() <= diagnostic_code::MAX_PUBLIC_DIAGNOSTIC_FACTS);
2181 facts
2182 }
2183}
2184
2185fn append_accepted_schema_facts(
2187 facts: &mut Vec<(diagnostic_code::DiagnosticFactTag, u64)>,
2188 method: u8,
2189 fingerprint: [u8; 16],
2190) {
2191 facts.extend([
2192 (
2193 diagnostic_code::DiagnosticFactTag::AcceptedSchemaFingerprintMethod,
2194 u64::from(method),
2195 ),
2196 (
2197 diagnostic_code::DiagnosticFactTag::AcceptedSchemaFingerprintHigh,
2198 u64::from_be_bytes([
2199 fingerprint[0],
2200 fingerprint[1],
2201 fingerprint[2],
2202 fingerprint[3],
2203 fingerprint[4],
2204 fingerprint[5],
2205 fingerprint[6],
2206 fingerprint[7],
2207 ]),
2208 ),
2209 (
2210 diagnostic_code::DiagnosticFactTag::AcceptedSchemaFingerprintLow,
2211 u64::from_be_bytes([
2212 fingerprint[8],
2213 fingerprint[9],
2214 fingerprint[10],
2215 fingerprint[11],
2216 fingerprint[12],
2217 fingerprint[13],
2218 fingerprint[14],
2219 fingerprint[15],
2220 ]),
2221 ),
2222 ]);
2223}
2224
2225fn constraint_value_path_fact(
2226 component: ConstraintValuePathComponent,
2227) -> (diagnostic_code::DiagnosticFactTag, u64) {
2228 use diagnostic_code::DiagnosticFactTag;
2229 match component {
2230 ConstraintValuePathComponent::RootField { field_id } => {
2231 (DiagnosticFactTag::RootField, u64::from(field_id))
2232 }
2233 ConstraintValuePathComponent::RecordMember {
2234 composite_type_id,
2235 member_id,
2236 } => (
2237 DiagnosticFactTag::RecordMember,
2238 diagnostic_code::pack_u32_pair(composite_type_id, member_id),
2239 ),
2240 ConstraintValuePathComponent::TupleElement {
2241 composite_type_id,
2242 ordinal,
2243 } => (
2244 DiagnosticFactTag::TupleElement,
2245 diagnostic_code::pack_u32_pair(composite_type_id, ordinal),
2246 ),
2247 ConstraintValuePathComponent::Newtype { composite_type_id } => {
2248 (DiagnosticFactTag::Newtype, u64::from(composite_type_id))
2249 }
2250 ConstraintValuePathComponent::EnumVariant {
2251 enum_type_id,
2252 variant_id,
2253 } => (
2254 DiagnosticFactTag::EnumVariant,
2255 diagnostic_code::pack_u32_pair(enum_type_id, variant_id),
2256 ),
2257 ConstraintValuePathComponent::ListElement { index } => {
2258 (DiagnosticFactTag::ListElement, u64::from(index))
2259 }
2260 ConstraintValuePathComponent::SetElement { index } => {
2261 (DiagnosticFactTag::SetElement, u64::from(index))
2262 }
2263 ConstraintValuePathComponent::MapEntryKey { index } => {
2264 (DiagnosticFactTag::MapEntryKey, u64::from(index))
2265 }
2266 ConstraintValuePathComponent::MapEntryValue { index } => {
2267 (DiagnosticFactTag::MapEntryValue, u64::from(index))
2268 }
2269 }
2270}
2271
2272pub enum ErrorDetail {
2280 DiagnosticFacts(Box<DiagnosticFactDetail>),
2282 Executor(ExecutorErrorDetail),
2284 Store(StoreError),
2285 Query(QueryErrorDetail),
2286 Recovery(RecoveryErrorDetail),
2287 }
2290
2291pub enum ExecutorErrorDetail {
2293 MutationRequiredFieldMissing,
2295 MutationManagedTimestampRegression,
2297 MutationDatabaseOwnedFieldExplicit,
2299 MutationBatchEmpty,
2301 MutationBatchTooManyItems,
2303 MutationBatchStagedBytesExceeded,
2305 MutationBatchResultBytesExceeded,
2307 MutationBatchStoreMismatch,
2309 MutationBatchTooManyEntities,
2311 MutationBatchDuplicateKey,
2313 AcceptedRowConstraintProgramCorrupt,
2315}
2316
2317pub enum RecoveryErrorDetail {
2324 UnsupportedFormatVersion { found: Option<u16>, required: u16 },
2325
2326 MalformedFormatMarker { reason: RecoveryFormatMarkerError },
2327}
2328
2329#[derive(Clone, Copy, Eq, PartialEq)]
2331pub enum RecoveryFormatMarkerError {
2332 Magic,
2333 Checksum,
2334 State,
2335}
2336
2337impl RecoveryFormatMarkerError {
2338 const fn diagnostic_decode_reason(self) -> diagnostic_code::DiagnosticDecodeReason {
2339 match self {
2340 Self::Magic => diagnostic_code::DiagnosticDecodeReason::RecoveryMarkerMagic,
2341 Self::Checksum => diagnostic_code::DiagnosticDecodeReason::RecoveryMarkerChecksum,
2342 Self::State => diagnostic_code::DiagnosticDecodeReason::RecoveryMarkerState,
2343 }
2344 }
2345}
2346
2347pub enum StoreError {
2355 NotFound,
2356
2357 Corrupt,
2358
2359 InvariantViolation,
2360
2361 SchemaDdlPublicationRaceLost,
2362
2363 SchemaDdlRewriteRequiresMigration,
2364
2365 SchemaMigration {
2366 reason: diagnostic_code::SchemaMigrationCode,
2367 },
2368
2369 SchemaRowLayoutVersionExhausted,
2370
2371 JournalMutationRevisionExhausted,
2372
2373 SchemaTransitionBudgetExceeded {
2374 resource: SchemaTransitionBudgetResource,
2375 },
2376
2377 SchemaGeneratedFieldAfterDdlField,
2379
2380 SchemaGeneratedConstraintActivationStale,
2382}
2383
2384pub enum QueryErrorDetail {
2391 ExactCountMetadataUnavailable,
2393
2394 NumericOverflow,
2395
2396 NumericNotRepresentable,
2397
2398 UnsupportedSqlFeature {
2399 feature: diagnostic_code::SqlFeatureCode,
2400 },
2401
2402 SqlLowering {
2403 reason: diagnostic_code::SqlLoweringCode,
2404 },
2405
2406 UnsupportedProjection {
2407 reason: diagnostic_code::QueryProjectionCode,
2408 },
2409
2410 UnknownAggregateTargetField,
2411
2412 QueryReadAdmission {
2413 reason: diagnostic_code::QueryReadAdmissionCode,
2414 },
2415
2416 SqlSurfaceMismatch {
2417 mismatch: diagnostic_code::SqlSurfaceMismatchCode,
2418 },
2419
2420 SqlWriteBoundary {
2421 boundary: diagnostic_code::SqlWriteBoundaryCode,
2422 },
2423
2424 SchemaDdlAdmission {
2425 error: SchemaDdlAdmissionError,
2426 },
2427
2428 StaleSchemaRevision,
2429}
2430
2431impl fmt::Display for QueryErrorDetail {
2432 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2433 f.write_str(COMPACT_QUERY_DIAGNOSTIC_MESSAGE)
2434 }
2435}
2436
2437impl std::error::Error for QueryErrorDetail {}
2438
2439#[derive(Clone, Copy, Debug, Eq, PartialEq)]
2447pub enum SchemaTransitionBudgetResource {
2448 DeletionKeys,
2450 ProjectionEntries,
2452 ProjectionWorkUnits,
2454 SourceRows,
2456 SourceRowBytes,
2458 StagedRawBytes,
2460}
2461
2462#[derive(Clone, Copy, Eq, PartialEq)]
2471pub enum SchemaDdlAdmissionError {
2472 MissingExpectedSchemaVersion,
2473
2474 MissingNextSchemaVersion,
2475
2476 StaleExpectedSchemaVersion,
2477
2478 InvalidExpectedSchemaVersion,
2479
2480 InvalidNextSchemaVersion,
2481
2482 AcceptedSchemaChangeWithoutVersionBump,
2483
2484 EmptyVersionBump,
2485
2486 VersionGap,
2487
2488 VersionRollback,
2489
2490 FingerprintMethodMismatch,
2491
2492 UnsupportedTransitionClass,
2493
2494 PhysicalRunnerMissing,
2495
2496 ValidationFailed,
2497
2498 PublicationRaceLost,
2499
2500 InvalidAddColumnDefault,
2501
2502 InvalidAlterColumnDefault,
2503
2504 RowLayoutVersionExhausted,
2505
2506 GeneratedIndexDropRejected,
2507
2508 SchemaRewriteRequiresMigration,
2509
2510 SchemaTransitionBudgetExceeded {
2511 resource: SchemaTransitionBudgetResource,
2512 },
2513
2514 GeneratedFieldDefaultChangeRejected,
2515
2516 GeneratedFieldNullabilityChangeRejected,
2517}
2518
2519impl fmt::Display for SchemaDdlAdmissionError {
2520 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2521 f.write_str(COMPACT_QUERY_DIAGNOSTIC_MESSAGE)
2522 }
2523}
2524
2525impl std::error::Error for SchemaDdlAdmissionError {}
2526
2527impl fmt::Debug for ErrorDetail {
2528 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2529 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2530 }
2531}
2532
2533impl fmt::Debug for ExecutorErrorDetail {
2534 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2535 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2536 }
2537}
2538
2539impl fmt::Debug for StoreError {
2540 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2541 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2542 }
2543}
2544
2545impl fmt::Debug for QueryErrorDetail {
2546 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2547 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2548 }
2549}
2550
2551impl fmt::Debug for RecoveryErrorDetail {
2552 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2553 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2554 }
2555}
2556
2557impl fmt::Debug for RecoveryFormatMarkerError {
2558 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2559 fmt_compact_diagnostic(
2560 f,
2561 diagnostic_code::DiagnosticCode::RuntimeCorruption,
2562 Some(diagnostic_code::DiagnosticDetail::RuntimeKind {
2563 kind: diagnostic_code::RuntimeErrorKind::Corruption,
2564 }),
2565 )
2566 }
2567}
2568
2569impl fmt::Debug for SchemaDdlAdmissionError {
2570 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2571 fmt_compact_diagnostic(
2572 f,
2573 diagnostic_code::DiagnosticCode::SchemaDdlAdmission,
2574 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2575 reason: self.diagnostic_code(),
2576 }),
2577 )
2578 }
2579}
2580
2581fn fmt_compact_diagnostic(
2582 f: &mut fmt::Formatter<'_>,
2583 code: diagnostic_code::DiagnosticCode,
2584 detail: Option<diagnostic_code::DiagnosticDetail>,
2585) -> fmt::Result {
2586 write!(
2587 f,
2588 "{}",
2589 diagnostic_code::ErrorCode::from_parts(code, detail).raw()
2590 )
2591}
2592
2593impl ErrorDetail {
2594 #[must_use]
2596 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2597 match self {
2598 Self::DiagnosticFacts(detail) => detail.diagnostic.code(),
2599 Self::Executor(error) => error.diagnostic_code(),
2600 Self::Store(error) => error.diagnostic_code(),
2601 Self::Query(error) => error.diagnostic_code(),
2602 Self::Recovery(error) => error.diagnostic_code(),
2603 }
2604 }
2605
2606 #[must_use]
2608 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2609 match self {
2610 Self::DiagnosticFacts(detail) => detail.diagnostic.detail().copied(),
2611 Self::Executor(error) => error.diagnostic_detail(),
2612 Self::Store(error) => error.diagnostic_detail(),
2613 Self::Query(error) => error.diagnostic_detail(),
2614 Self::Recovery(error) => error.diagnostic_detail(),
2615 }
2616 }
2617
2618 #[must_use]
2620 #[cold]
2621 #[inline(never)]
2622 pub fn diagnostic_facts(&self) -> Vec<(diagnostic_code::DiagnosticFactTag, u64)> {
2623 match self {
2624 Self::DiagnosticFacts(detail) => detail.facts.clone(),
2625 Self::Executor(error) => error.diagnostic_facts(),
2626 Self::Query(error) => error.diagnostic_facts(),
2627 Self::Recovery(error) => error.diagnostic_facts(),
2628 Self::Store(_) => Vec::new(),
2629 }
2630 }
2631}
2632
2633impl ExecutorErrorDetail {
2634 #[must_use]
2636 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2637 match self {
2638 Self::MutationRequiredFieldMissing
2639 | Self::MutationDatabaseOwnedFieldExplicit
2640 | Self::MutationBatchEmpty
2641 | Self::MutationBatchTooManyItems
2642 | Self::MutationBatchTooManyEntities
2643 | Self::MutationBatchStagedBytesExceeded
2644 | Self::MutationBatchResultBytesExceeded => {
2645 diagnostic_code::DiagnosticCode::RuntimeUnsupported
2646 }
2647 Self::MutationBatchStoreMismatch | Self::MutationBatchDuplicateKey => {
2648 diagnostic_code::DiagnosticCode::RuntimeConflict
2649 }
2650 Self::MutationManagedTimestampRegression => {
2651 diagnostic_code::DiagnosticCode::RuntimeInvariantViolation
2652 }
2653 Self::AcceptedRowConstraintProgramCorrupt => {
2654 diagnostic_code::DiagnosticCode::RuntimeCorruption
2655 }
2656 }
2657 }
2658
2659 #[must_use]
2661 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2662 match self {
2663 Self::MutationRequiredFieldMissing => {
2664 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2665 boundary: diagnostic_code::RuntimeBoundaryCode::MutationRequiredFieldMissing,
2666 })
2667 }
2668 Self::MutationDatabaseOwnedFieldExplicit => {
2669 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2670 boundary:
2671 diagnostic_code::RuntimeBoundaryCode::MutationDatabaseOwnedFieldExplicit,
2672 })
2673 }
2674 Self::MutationBatchEmpty => Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2675 boundary: diagnostic_code::RuntimeBoundaryCode::MutationBatchEmpty,
2676 }),
2677 Self::MutationBatchTooManyItems => {
2678 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2679 boundary: diagnostic_code::RuntimeBoundaryCode::MutationBatchTooManyItems,
2680 })
2681 }
2682 Self::MutationBatchStagedBytesExceeded => {
2683 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2684 boundary:
2685 diagnostic_code::RuntimeBoundaryCode::MutationBatchStagedBytesExceeded,
2686 })
2687 }
2688 Self::MutationBatchResultBytesExceeded => {
2689 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2690 boundary:
2691 diagnostic_code::RuntimeBoundaryCode::MutationBatchResultBytesExceeded,
2692 })
2693 }
2694 Self::MutationBatchStoreMismatch => {
2695 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2696 boundary: diagnostic_code::RuntimeBoundaryCode::MutationBatchStoreMismatch,
2697 })
2698 }
2699 Self::MutationBatchTooManyEntities => {
2700 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2701 boundary: diagnostic_code::RuntimeBoundaryCode::MutationBatchTooManyEntities,
2702 })
2703 }
2704 Self::MutationBatchDuplicateKey => {
2705 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2706 boundary: diagnostic_code::RuntimeBoundaryCode::MutationBatchDuplicateKey,
2707 })
2708 }
2709 Self::MutationManagedTimestampRegression => {
2710 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2711 boundary:
2712 diagnostic_code::RuntimeBoundaryCode::MutationManagedTimestampRegression,
2713 })
2714 }
2715 Self::AcceptedRowConstraintProgramCorrupt => {
2716 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2717 boundary:
2718 diagnostic_code::RuntimeBoundaryCode::AcceptedRowConstraintProgramCorrupt,
2719 })
2720 }
2721 }
2722 }
2723
2724 #[must_use]
2726 #[cold]
2727 #[inline(never)]
2728 pub const fn diagnostic_facts(&self) -> Vec<(diagnostic_code::DiagnosticFactTag, u64)> {
2729 Vec::new()
2730 }
2731}
2732
2733impl RecoveryErrorDetail {
2734 #[must_use]
2736 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2737 match self {
2738 Self::UnsupportedFormatVersion { .. } => {
2739 diagnostic_code::DiagnosticCode::RuntimeIncompatiblePersistedFormat
2740 }
2741 Self::MalformedFormatMarker { .. } => {
2742 diagnostic_code::DiagnosticCode::RuntimeCorruption
2743 }
2744 }
2745 }
2746
2747 #[must_use]
2749 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2750 let kind = match self {
2751 Self::UnsupportedFormatVersion { .. } => {
2752 diagnostic_code::RuntimeErrorKind::IncompatiblePersistedFormat
2753 }
2754 Self::MalformedFormatMarker { .. } => diagnostic_code::RuntimeErrorKind::Corruption,
2755 };
2756
2757 Some(diagnostic_code::DiagnosticDetail::RuntimeKind { kind })
2758 }
2759
2760 #[must_use]
2762 pub fn diagnostic_facts(&self) -> Vec<(diagnostic_code::DiagnosticFactTag, u64)> {
2763 match self {
2764 Self::UnsupportedFormatVersion { found, required } => {
2765 let mut facts = Vec::with_capacity(usize::from(found.is_some()) + 1);
2766 facts.push((
2767 diagnostic_code::DiagnosticFactTag::ExpectedVersion,
2768 u64::from(*required),
2769 ));
2770 if let Some(found) = found {
2771 facts.push((
2772 diagnostic_code::DiagnosticFactTag::ActualVersion,
2773 u64::from(*found),
2774 ));
2775 }
2776 facts
2777 }
2778 Self::MalformedFormatMarker { reason } => vec![(
2779 diagnostic_code::DiagnosticFactTag::DecodeReason,
2780 reason.diagnostic_decode_reason().raw(),
2781 )],
2782 }
2783 }
2784}
2785
2786impl StoreError {
2787 #[must_use]
2789 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2790 match self {
2791 Self::NotFound => diagnostic_code::DiagnosticCode::StoreNotFound,
2792 Self::Corrupt => diagnostic_code::DiagnosticCode::StoreCorruption,
2793 Self::InvariantViolation => diagnostic_code::DiagnosticCode::StoreInvariantViolation,
2794 Self::SchemaDdlPublicationRaceLost
2795 | Self::SchemaDdlRewriteRequiresMigration
2796 | Self::SchemaRowLayoutVersionExhausted
2797 | Self::SchemaTransitionBudgetExceeded { .. } => {
2798 diagnostic_code::DiagnosticCode::SchemaDdlAdmission
2799 }
2800 Self::JournalMutationRevisionExhausted | Self::SchemaGeneratedFieldAfterDdlField => {
2801 diagnostic_code::DiagnosticCode::RuntimeUnsupported
2802 }
2803 Self::SchemaGeneratedConstraintActivationStale => {
2804 diagnostic_code::DiagnosticCode::RuntimeConflict
2805 }
2806 Self::SchemaMigration { reason } => reason.diagnostic_code(),
2807 }
2808 }
2809
2810 #[must_use]
2812 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2813 match self {
2814 Self::SchemaDdlPublicationRaceLost => {
2815 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2816 reason: diagnostic_code::SchemaDdlAdmissionCode::PublicationRaceLost,
2817 })
2818 }
2819 Self::SchemaDdlRewriteRequiresMigration => {
2820 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2821 reason: diagnostic_code::SchemaDdlAdmissionCode::SchemaRewriteRequiresMigration,
2822 })
2823 }
2824 Self::SchemaMigration { reason } => {
2825 Some(diagnostic_code::DiagnosticDetail::SchemaMigration { reason: *reason })
2826 }
2827 Self::SchemaRowLayoutVersionExhausted => {
2828 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2829 reason: diagnostic_code::SchemaDdlAdmissionCode::RowLayoutVersionExhausted,
2830 })
2831 }
2832 Self::JournalMutationRevisionExhausted => {
2833 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2834 boundary:
2835 diagnostic_code::RuntimeBoundaryCode::JournalMutationRevisionExhausted,
2836 })
2837 }
2838 Self::SchemaTransitionBudgetExceeded { .. } => {
2839 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2840 reason: diagnostic_code::SchemaDdlAdmissionCode::SchemaTransitionBudgetExceeded,
2841 })
2842 }
2843 Self::SchemaGeneratedFieldAfterDdlField => {
2844 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2845 boundary: diagnostic_code::RuntimeBoundaryCode::GeneratedFieldAfterDdlField,
2846 })
2847 }
2848 Self::SchemaGeneratedConstraintActivationStale => {
2849 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2850 boundary:
2851 diagnostic_code::RuntimeBoundaryCode::GeneratedConstraintActivationStale,
2852 })
2853 }
2854 Self::NotFound | Self::Corrupt | Self::InvariantViolation => None,
2855 }
2856 }
2857}
2858
2859impl QueryErrorDetail {
2860 #[must_use]
2862 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2863 match self {
2864 Self::ExactCountMetadataUnavailable => {
2865 diagnostic_code::DiagnosticCode::QueryExactCountMetadataUnavailable
2866 }
2867 Self::NumericOverflow => diagnostic_code::DiagnosticCode::QueryNumericOverflow,
2868 Self::NumericNotRepresentable => {
2869 diagnostic_code::DiagnosticCode::QueryNumericNotRepresentable
2870 }
2871 Self::UnsupportedSqlFeature { .. } => {
2872 diagnostic_code::DiagnosticCode::QueryUnsupportedSqlFeature
2873 }
2874 Self::SqlLowering { .. } => diagnostic_code::DiagnosticCode::QueryUnsupportedSqlFeature,
2875 Self::UnsupportedProjection { .. } => {
2876 diagnostic_code::DiagnosticCode::QueryUnsupportedProjection
2877 }
2878 Self::UnknownAggregateTargetField => {
2879 diagnostic_code::DiagnosticCode::QueryUnknownAggregateTargetField
2880 }
2881 Self::QueryReadAdmission { .. } => diagnostic_code::DiagnosticCode::QueryReadAdmission,
2882 Self::SqlSurfaceMismatch { .. } => {
2883 diagnostic_code::DiagnosticCode::QuerySqlSurfaceMismatch
2884 }
2885 Self::SqlWriteBoundary { .. } => diagnostic_code::DiagnosticCode::QuerySqlWriteBoundary,
2886 Self::SchemaDdlAdmission { .. } => diagnostic_code::DiagnosticCode::SchemaDdlAdmission,
2887 Self::StaleSchemaRevision => diagnostic_code::DiagnosticCode::RuntimeConflict,
2888 }
2889 }
2890
2891 #[must_use]
2893 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2894 match self {
2895 Self::UnsupportedSqlFeature { feature } => {
2896 Some(diagnostic_code::DiagnosticDetail::UnsupportedSqlFeature { feature: *feature })
2897 }
2898 Self::SqlLowering { reason } => {
2899 Some(diagnostic_code::DiagnosticDetail::SqlLowering { reason: *reason })
2900 }
2901 Self::UnsupportedProjection { reason } => {
2902 Some(diagnostic_code::DiagnosticDetail::QueryProjection { reason: *reason })
2903 }
2904 Self::QueryReadAdmission { reason } => {
2905 Some(diagnostic_code::DiagnosticDetail::QueryReadAdmission { reason: *reason })
2906 }
2907 Self::SqlSurfaceMismatch { mismatch } => {
2908 Some(diagnostic_code::DiagnosticDetail::SqlSurfaceMismatch {
2909 mismatch: *mismatch,
2910 })
2911 }
2912 Self::SqlWriteBoundary { boundary } => {
2913 Some(diagnostic_code::DiagnosticDetail::SqlWriteBoundary {
2914 boundary: *boundary,
2915 })
2916 }
2917 Self::SchemaDdlAdmission { error } => {
2918 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2919 reason: error.diagnostic_code(),
2920 })
2921 }
2922 Self::ExactCountMetadataUnavailable
2923 | Self::NumericOverflow
2924 | Self::NumericNotRepresentable
2925 | Self::UnknownAggregateTargetField
2926 | Self::StaleSchemaRevision => None,
2927 }
2928 }
2929
2930 #[must_use]
2932 #[cold]
2933 #[inline(never)]
2934 pub const fn diagnostic_facts(&self) -> Vec<(diagnostic_code::DiagnosticFactTag, u64)> {
2935 Vec::new()
2936 }
2937}
2938
2939impl SchemaDdlAdmissionError {
2940 #[must_use]
2942 pub const fn diagnostic_code(&self) -> diagnostic_code::SchemaDdlAdmissionCode {
2943 match self {
2944 Self::MissingExpectedSchemaVersion => {
2945 diagnostic_code::SchemaDdlAdmissionCode::MissingExpectedSchemaVersion
2946 }
2947 Self::MissingNextSchemaVersion => {
2948 diagnostic_code::SchemaDdlAdmissionCode::MissingNextSchemaVersion
2949 }
2950 Self::StaleExpectedSchemaVersion => {
2951 diagnostic_code::SchemaDdlAdmissionCode::StaleExpectedSchemaVersion
2952 }
2953 Self::InvalidExpectedSchemaVersion => {
2954 diagnostic_code::SchemaDdlAdmissionCode::InvalidExpectedSchemaVersion
2955 }
2956 Self::InvalidNextSchemaVersion => {
2957 diagnostic_code::SchemaDdlAdmissionCode::InvalidNextSchemaVersion
2958 }
2959 Self::AcceptedSchemaChangeWithoutVersionBump => {
2960 diagnostic_code::SchemaDdlAdmissionCode::AcceptedSchemaChangeWithoutVersionBump
2961 }
2962 Self::EmptyVersionBump => diagnostic_code::SchemaDdlAdmissionCode::EmptyVersionBump,
2963 Self::VersionGap => diagnostic_code::SchemaDdlAdmissionCode::VersionGap,
2964 Self::VersionRollback => diagnostic_code::SchemaDdlAdmissionCode::VersionRollback,
2965 Self::FingerprintMethodMismatch => {
2966 diagnostic_code::SchemaDdlAdmissionCode::FingerprintMethodMismatch
2967 }
2968 Self::UnsupportedTransitionClass => {
2969 diagnostic_code::SchemaDdlAdmissionCode::UnsupportedTransitionClass
2970 }
2971 Self::PhysicalRunnerMissing => {
2972 diagnostic_code::SchemaDdlAdmissionCode::PhysicalRunnerMissing
2973 }
2974 Self::ValidationFailed => diagnostic_code::SchemaDdlAdmissionCode::ValidationFailed,
2975 Self::PublicationRaceLost => {
2976 diagnostic_code::SchemaDdlAdmissionCode::PublicationRaceLost
2977 }
2978 Self::InvalidAddColumnDefault => {
2979 diagnostic_code::SchemaDdlAdmissionCode::InvalidAddColumnDefault
2980 }
2981 Self::InvalidAlterColumnDefault => {
2982 diagnostic_code::SchemaDdlAdmissionCode::InvalidAlterColumnDefault
2983 }
2984 Self::GeneratedIndexDropRejected => {
2985 diagnostic_code::SchemaDdlAdmissionCode::GeneratedIndexDropRejected
2986 }
2987 Self::SchemaRewriteRequiresMigration => {
2988 diagnostic_code::SchemaDdlAdmissionCode::SchemaRewriteRequiresMigration
2989 }
2990 Self::SchemaTransitionBudgetExceeded { .. } => {
2991 diagnostic_code::SchemaDdlAdmissionCode::SchemaTransitionBudgetExceeded
2992 }
2993 Self::GeneratedFieldDefaultChangeRejected => {
2994 diagnostic_code::SchemaDdlAdmissionCode::GeneratedFieldDefaultChangeRejected
2995 }
2996 Self::GeneratedFieldNullabilityChangeRejected => {
2997 diagnostic_code::SchemaDdlAdmissionCode::GeneratedFieldNullabilityChangeRejected
2998 }
2999 Self::RowLayoutVersionExhausted => {
3000 diagnostic_code::SchemaDdlAdmissionCode::RowLayoutVersionExhausted
3001 }
3002 }
3003 }
3004}
3005
3006#[repr(u8)]
3013#[derive(Clone, Copy, Eq, PartialEq)]
3014pub enum ErrorClass {
3015 Corruption,
3016 IncompatiblePersistedFormat,
3017 NotFound,
3018 Internal,
3019 Conflict,
3020 Unsupported,
3021 InvariantViolation,
3022}
3023
3024impl ErrorClass {
3025 #[must_use]
3027 pub const fn diagnostic_code(self, origin: ErrorOrigin) -> diagnostic_code::DiagnosticCode {
3028 match self {
3029 Self::Corruption if matches!(origin, ErrorOrigin::Store) => {
3030 diagnostic_code::DiagnosticCode::StoreCorruption
3031 }
3032 Self::Corruption => diagnostic_code::DiagnosticCode::RuntimeCorruption,
3033 Self::IncompatiblePersistedFormat => {
3034 diagnostic_code::DiagnosticCode::RuntimeIncompatiblePersistedFormat
3035 }
3036 Self::NotFound if matches!(origin, ErrorOrigin::Store) => {
3037 diagnostic_code::DiagnosticCode::StoreNotFound
3038 }
3039 Self::NotFound => diagnostic_code::DiagnosticCode::RuntimeNotFound,
3040 Self::Internal => diagnostic_code::DiagnosticCode::RuntimeInternal,
3041 Self::Conflict => diagnostic_code::DiagnosticCode::RuntimeConflict,
3042 Self::Unsupported if matches!(origin, ErrorOrigin::Cursor) => {
3043 diagnostic_code::DiagnosticCode::QueryInvalidContinuationCursor
3044 }
3045 Self::Unsupported => diagnostic_code::DiagnosticCode::RuntimeUnsupported,
3046 Self::InvariantViolation if matches!(origin, ErrorOrigin::Store) => {
3047 diagnostic_code::DiagnosticCode::StoreInvariantViolation
3048 }
3049 Self::InvariantViolation => diagnostic_code::DiagnosticCode::RuntimeInvariantViolation,
3050 }
3051 }
3052}
3053
3054impl fmt::Debug for ErrorClass {
3055 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3056 write!(f, "{}", *self as u8)
3057 }
3058}
3059
3060#[repr(u8)]
3067#[derive(Clone, Copy, Eq, PartialEq)]
3068pub enum ErrorOrigin {
3069 Serialize,
3070 Store,
3071 Index,
3072 Identity,
3073 Query,
3074 Planner,
3075 Cursor,
3076 Recovery,
3077 Response,
3078 Executor,
3079 Interface,
3080}
3081
3082impl ErrorOrigin {
3083 #[must_use]
3085 pub const fn diagnostic_origin(self) -> diagnostic_code::ErrorOrigin {
3086 match self {
3087 Self::Serialize => diagnostic_code::ErrorOrigin::Serialize,
3088 Self::Store => diagnostic_code::ErrorOrigin::Store,
3089 Self::Index => diagnostic_code::ErrorOrigin::Index,
3090 Self::Identity => diagnostic_code::ErrorOrigin::Identity,
3091 Self::Query => diagnostic_code::ErrorOrigin::Query,
3092 Self::Planner => diagnostic_code::ErrorOrigin::Planner,
3093 Self::Cursor => diagnostic_code::ErrorOrigin::Cursor,
3094 Self::Recovery => diagnostic_code::ErrorOrigin::Recovery,
3095 Self::Response => diagnostic_code::ErrorOrigin::Response,
3096 Self::Executor => diagnostic_code::ErrorOrigin::Executor,
3097 Self::Interface => diagnostic_code::ErrorOrigin::Interface,
3098 }
3099 }
3100}
3101
3102impl fmt::Debug for ErrorOrigin {
3103 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3104 write!(f, "{}", *self as u8)
3105 }
3106}