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