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