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_store_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::MutationBatchStoreMismatch,
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 #[cold]
925 #[inline(never)]
926 pub(crate) fn mutation_batch_too_many_entities(actual_count: usize, limit: usize) -> Self {
927 Self::mutation_boundary_with_facts(
928 ErrorClass::Unsupported,
929 diagnostic_code::RuntimeBoundaryCode::MutationBatchTooManyEntities,
930 vec![
931 (
932 diagnostic_code::DiagnosticFactTag::ActualCount,
933 actual_count as u64,
934 ),
935 (diagnostic_code::DiagnosticFactTag::Limit, limit as u64),
936 ],
937 )
938 }
939
940 pub(crate) fn mutation_index_store_generation_changed(
942 _expected_generation: u64,
943 _observed_generation: u64,
944 ) -> Self {
945 Self::executor_invariant()
946 }
947
948 #[cold]
950 #[inline(never)]
951 pub(crate) fn planner_invariant() -> Self {
952 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Planner)
953 }
954
955 pub(crate) fn query_invalid_logical_plan() -> Self {
957 Self::planner_invariant()
958 }
959
960 pub(crate) fn store_invariant() -> Self {
962 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Store)
963 }
964
965 #[cold]
967 #[inline(never)]
968 pub(crate) fn store_internal() -> Self {
969 Self::new(ErrorClass::Internal, ErrorOrigin::Store)
970 }
971
972 pub(crate) fn commit_memory_id_unconfigured() -> Self {
974 Self::store_internal()
975 }
976
977 pub(crate) fn commit_store_uninitialized() -> Self {
979 Self::store_invariant()
980 }
981
982 pub(crate) fn commit_memory_id_mismatch(cached_id: u8, configured_id: u8) -> Self {
984 Self::with_diagnostic_facts(
985 ErrorClass::Internal,
986 ErrorOrigin::Store,
987 None,
988 vec![
989 (
990 diagnostic_code::DiagnosticFactTag::ExpectedMemoryId,
991 u64::from(cached_id),
992 ),
993 (
994 diagnostic_code::DiagnosticFactTag::ActualMemoryId,
995 u64::from(configured_id),
996 ),
997 ],
998 )
999 }
1000
1001 pub(crate) fn commit_memory_stable_key_mismatch(
1003 _cached_key: &str,
1004 _configured_key: &str,
1005 ) -> Self {
1006 Self::store_internal()
1007 }
1008
1009 pub(crate) fn database_incarnation_generation_failed() -> Self {
1011 Self::store_internal()
1012 }
1013
1014 pub(crate) fn database_incarnation_invalid() -> Self {
1016 Self::store_corruption()
1017 }
1018
1019 pub(crate) fn recovery_unsupported_database_format(found: Option<u16>, required: u16) -> Self {
1021 Self {
1022 class: ErrorClass::IncompatiblePersistedFormat,
1023 origin: ErrorOrigin::Recovery,
1024 detail: Some(ErrorDetail::Recovery(
1025 RecoveryErrorDetail::UnsupportedFormatVersion { found, required },
1026 )),
1027 }
1028 }
1029
1030 pub(crate) fn recovery_malformed_database_format_marker(
1032 reason: RecoveryFormatMarkerError,
1033 ) -> Self {
1034 Self {
1035 class: ErrorClass::Corruption,
1036 origin: ErrorOrigin::Recovery,
1037 detail: Some(ErrorDetail::Recovery(
1038 RecoveryErrorDetail::MalformedFormatMarker { reason },
1039 )),
1040 }
1041 }
1042
1043 pub(crate) fn recovery_database_format_control_unavailable() -> Self {
1045 Self::new(ErrorClass::Internal, ErrorOrigin::Recovery)
1046 }
1047
1048 pub(crate) fn recovery_pending() -> Self {
1050 Self::with_diagnostic_facts(
1051 ErrorClass::Conflict,
1052 ErrorOrigin::Recovery,
1053 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
1054 boundary: diagnostic_code::RuntimeBoundaryCode::DatabaseStartupRecoveryPending,
1055 }),
1056 Vec::new(),
1057 )
1058 }
1059
1060 pub(crate) fn startup_control_corruption() -> Self {
1062 Self::new(ErrorClass::Corruption, ErrorOrigin::Recovery)
1063 }
1064
1065 pub(crate) fn commit_control_memory_growth_failed() -> Self {
1067 Self::store_internal()
1068 }
1069
1070 #[cfg(not(test))]
1072 pub(crate) fn database_format_memory_registration_failed(_err: impl Sized) -> Self {
1073 Self::store_internal()
1074 }
1075
1076 pub(crate) fn recovery_effect_verification_failed() -> Self {
1078 Self::store_corruption()
1079 }
1080
1081 #[cold]
1083 #[inline(never)]
1084 pub(crate) fn index_internal() -> Self {
1085 Self::new(ErrorClass::Internal, ErrorOrigin::Index)
1086 }
1087
1088 pub(crate) fn structural_index_removal_entity_key_required() -> Self {
1090 Self::index_internal()
1091 }
1092
1093 pub(crate) fn structural_index_insertion_entity_key_required() -> Self {
1095 Self::index_internal()
1096 }
1097
1098 pub(crate) fn index_commit_op_old_entity_key_required() -> Self {
1100 Self::index_internal()
1101 }
1102
1103 pub(crate) fn index_commit_op_new_entity_key_required() -> Self {
1105 Self::index_internal()
1106 }
1107
1108 #[cfg(test)]
1110 pub(crate) fn query_internal() -> Self {
1111 Self::new(ErrorClass::Internal, ErrorOrigin::Query)
1112 }
1113
1114 #[cold]
1116 #[inline(never)]
1117 pub(crate) fn query_unsupported() -> Self {
1118 Self::new(ErrorClass::Unsupported, ErrorOrigin::Query)
1119 }
1120
1121 #[cold]
1124 #[inline(never)]
1125 pub(crate) fn query_stale_accepted_schema_revision(
1126 expected_revision: u64,
1127 current_revision: Option<u64>,
1128 ) -> Self {
1129 let mut facts = Vec::with_capacity(1 + usize::from(current_revision.is_some()));
1130 facts.push((
1131 diagnostic_code::DiagnosticFactTag::ExpectedRevision,
1132 expected_revision,
1133 ));
1134 if let Some(current_revision) = current_revision {
1135 facts.push((
1136 diagnostic_code::DiagnosticFactTag::CurrentRevision,
1137 current_revision,
1138 ));
1139 }
1140 Self::with_diagnostic_facts(ErrorClass::Conflict, ErrorOrigin::Query, None, facts)
1141 }
1142
1143 #[cold]
1145 #[inline(never)]
1146 #[cfg(feature = "sql")]
1147 pub(crate) fn query_schema_ddl_admission(error: SchemaDdlAdmissionError) -> Self {
1148 Self {
1149 class: ErrorClass::Unsupported,
1150 origin: ErrorOrigin::Query,
1151 detail: Some(ErrorDetail::Query(QueryErrorDetail::SchemaDdlAdmission {
1152 error,
1153 })),
1154 }
1155 }
1156
1157 #[cold]
1159 #[inline(never)]
1160 pub(crate) fn query_numeric_overflow() -> Self {
1161 Self {
1162 class: ErrorClass::Unsupported,
1163 origin: ErrorOrigin::Query,
1164 detail: Some(ErrorDetail::Query(QueryErrorDetail::NumericOverflow)),
1165 }
1166 }
1167
1168 #[cold]
1171 #[inline(never)]
1172 pub(crate) fn query_numeric_not_representable() -> Self {
1173 Self {
1174 class: ErrorClass::Unsupported,
1175 origin: ErrorOrigin::Query,
1176 detail: Some(ErrorDetail::Query(
1177 QueryErrorDetail::NumericNotRepresentable,
1178 )),
1179 }
1180 }
1181
1182 #[cold]
1184 #[inline(never)]
1185 pub(crate) fn serialize_internal() -> Self {
1186 Self::new(ErrorClass::Internal, ErrorOrigin::Serialize)
1187 }
1188
1189 pub(crate) fn persisted_row_encode_failed(_detail: impl Sized) -> Self {
1191 Self::persisted_row_encode_internal()
1192 }
1193
1194 pub(crate) fn persisted_row_encode_internal() -> Self {
1196 Self::serialize_internal()
1197 }
1198
1199 pub(crate) fn persisted_row_field_encode_internal(_field_name: &str) -> Self {
1201 Self::persisted_row_encode_internal()
1202 }
1203
1204 #[cold]
1206 #[inline(never)]
1207 pub(crate) fn store_corruption() -> Self {
1208 Self::new(ErrorClass::Corruption, ErrorOrigin::Store)
1209 }
1210
1211 pub(crate) fn commit_corruption() -> Self {
1213 Self::store_corruption()
1214 }
1215
1216 pub(crate) fn commit_component_corruption() -> Self {
1218 Self::commit_corruption()
1219 }
1220
1221 pub(crate) fn commit_id_generation_failed() -> Self {
1223 Self::store_internal()
1224 }
1225
1226 pub(crate) fn commit_marker_payload_exceeds_u32_length_limit() -> Self {
1228 Self::store_unsupported()
1229 }
1230
1231 pub(crate) fn commit_component_length_invalid(actual_length: usize, limit: usize) -> Self {
1233 Self::with_diagnostic_facts(
1234 ErrorClass::Corruption,
1235 ErrorOrigin::Store,
1236 None,
1237 vec![
1238 (
1239 diagnostic_code::DiagnosticFactTag::ComponentKind,
1240 diagnostic_code::DiagnosticComponentKind::CommitDataKey.raw(),
1241 ),
1242 (
1243 diagnostic_code::DiagnosticFactTag::ActualLength,
1244 actual_length as u64,
1245 ),
1246 (diagnostic_code::DiagnosticFactTag::Limit, limit as u64),
1247 ],
1248 )
1249 }
1250
1251 pub(crate) fn commit_marker_exceeds_max_size() -> Self {
1253 Self::commit_corruption()
1254 }
1255
1256 pub(crate) fn commit_control_slot_exceeds_max_size() -> Self {
1258 Self::store_unsupported()
1259 }
1260
1261 pub(crate) fn commit_control_slot_marker_bytes_exceed_u32_length_limit() -> Self {
1263 Self::store_unsupported()
1264 }
1265
1266 #[cold]
1268 #[inline(never)]
1269 pub(crate) fn index_corruption() -> Self {
1270 Self::new(ErrorClass::Corruption, ErrorOrigin::Index)
1271 }
1272
1273 pub(crate) fn index_unique_validation_corruption() -> Self {
1275 Self::index_plan_index_corruption()
1276 }
1277
1278 pub(crate) fn structural_index_entry_corruption() -> Self {
1280 Self::index_plan_index_corruption()
1281 }
1282
1283 pub(crate) fn index_unique_validation_entity_key_required() -> Self {
1285 Self::index_invariant()
1286 }
1287
1288 pub(crate) fn index_unique_validation_row_deserialize_failed() -> Self {
1290 Self::index_plan_serialize_corruption()
1291 }
1292
1293 pub(crate) fn index_unique_validation_primary_key_decode_failed() -> Self {
1295 Self::index_plan_serialize_corruption()
1296 }
1297
1298 pub(crate) fn index_unique_validation_key_rebuild_failed() -> Self {
1300 Self::index_plan_serialize_corruption()
1301 }
1302
1303 pub(crate) fn index_unique_validation_row_required() -> Self {
1305 Self::index_plan_store_corruption()
1306 }
1307
1308 pub(crate) fn index_only_predicate_component_required() -> Self {
1310 Self::index_invariant()
1311 }
1312
1313 pub(crate) fn index_scan_continuation_anchor_within_envelope_required() -> Self {
1315 Self::index_invariant()
1316 }
1317
1318 pub(crate) fn index_scan_continuation_advancement_required() -> Self {
1320 Self::index_invariant()
1321 }
1322
1323 pub(crate) fn index_scan_key_corrupted_during(
1325 _context: &'static str,
1326 _err: impl Sized,
1327 ) -> Self {
1328 Self::index_corruption()
1329 }
1330
1331 pub(crate) fn index_projection_component_required(
1333 _index_name: &str,
1334 _component_index: usize,
1335 ) -> Self {
1336 Self::index_invariant()
1337 }
1338
1339 pub(crate) fn index_entry_decode_failed() -> Self {
1341 Self::index_corruption()
1342 }
1343
1344 pub(crate) fn serialize_corruption() -> Self {
1346 Self::new(ErrorClass::Corruption, ErrorOrigin::Serialize)
1347 }
1348
1349 pub(crate) fn persisted_row_decode_corruption() -> Self {
1351 Self::serialize_corruption()
1352 }
1353
1354 pub(crate) fn persisted_row_layout_outside_accepted_window(
1356 row_layout: u32,
1357 history_floor: u32,
1358 current_layout: u32,
1359 ) -> Self {
1360 Self::with_diagnostic_facts(
1361 ErrorClass::Corruption,
1362 ErrorOrigin::Serialize,
1363 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
1364 boundary:
1365 diagnostic_code::RuntimeBoundaryCode::PersistedRowLayoutOutsideAcceptedWindow,
1366 }),
1367 vec![
1368 (
1369 diagnostic_code::DiagnosticFactTag::RowLayout,
1370 u64::from(row_layout),
1371 ),
1372 (
1373 diagnostic_code::DiagnosticFactTag::HistoryFloor,
1374 u64::from(history_floor),
1375 ),
1376 (
1377 diagnostic_code::DiagnosticFactTag::CurrentLayout,
1378 u64::from(current_layout),
1379 ),
1380 ],
1381 )
1382 }
1383
1384 pub(crate) fn persisted_row_slot_count_mismatch(
1386 row_layout: u32,
1387 expected_slot_count: usize,
1388 actual_slot_count: usize,
1389 ) -> Self {
1390 Self::with_diagnostic_facts(
1391 ErrorClass::Corruption,
1392 ErrorOrigin::Serialize,
1393 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
1394 boundary: diagnostic_code::RuntimeBoundaryCode::PersistedRowSlotCountMismatch,
1395 }),
1396 vec![
1397 (
1398 diagnostic_code::DiagnosticFactTag::RowLayout,
1399 u64::from(row_layout),
1400 ),
1401 (
1402 diagnostic_code::DiagnosticFactTag::ExpectedSlotCount,
1403 expected_slot_count as u64,
1404 ),
1405 (
1406 diagnostic_code::DiagnosticFactTag::ActualSlotCount,
1407 actual_slot_count as u64,
1408 ),
1409 ],
1410 )
1411 }
1412
1413 pub(crate) fn persisted_row_field_decode_failed(field_name: &str, _detail: impl Sized) -> Self {
1415 Self::persisted_row_field_decode_corruption(field_name)
1416 }
1417
1418 pub(crate) fn persisted_row_field_decode_corruption(_field_name: &str) -> Self {
1420 Self::persisted_row_decode_corruption()
1421 }
1422
1423 pub(crate) fn persisted_row_field_kind_decode_failed(
1425 field_name: &str,
1426 _field_kind: impl fmt::Debug,
1427 _detail: impl Sized,
1428 ) -> Self {
1429 Self::persisted_row_field_decode_corruption(field_name)
1430 }
1431
1432 pub(crate) fn persisted_row_field_payload_exact_len_required(field_name: &str) -> Self {
1434 Self::persisted_row_field_decode_corruption(field_name)
1435 }
1436
1437 pub(crate) fn persisted_row_field_payload_must_be_empty(field_name: &str) -> Self {
1439 Self::persisted_row_field_decode_corruption(field_name)
1440 }
1441
1442 pub(crate) fn persisted_row_field_payload_invalid_byte(field_name: &str) -> Self {
1444 Self::persisted_row_field_decode_corruption(field_name)
1445 }
1446
1447 pub(crate) fn persisted_row_field_payload_non_finite(field_name: &str) -> Self {
1449 Self::persisted_row_field_decode_corruption(field_name)
1450 }
1451
1452 pub(crate) fn persisted_row_field_text_payload_invalid_utf8(field_name: &str) -> Self {
1454 Self::persisted_row_field_decode_corruption(field_name)
1455 }
1456
1457 pub(crate) fn persisted_row_slot_lookup_out_of_bounds(_model_path: &str, _slot: usize) -> Self {
1459 Self::index_invariant()
1460 }
1461
1462 pub(crate) fn persisted_row_slot_cache_lookup_out_of_bounds(
1464 _model_path: &str,
1465 _slot: usize,
1466 ) -> Self {
1467 Self::index_invariant()
1468 }
1469
1470 pub(crate) fn persisted_row_primary_key_not_primary_key_encodable(
1472 _data_key: impl fmt::Debug,
1473 _detail: impl Sized,
1474 ) -> Self {
1475 Self::persisted_row_decode_corruption()
1476 }
1477
1478 pub(crate) fn persisted_row_primary_key_slot_missing(_data_key: impl fmt::Debug) -> Self {
1480 Self::persisted_row_decode_corruption()
1481 }
1482
1483 pub(crate) fn persisted_row_key_mismatch() -> Self {
1485 Self::store_corruption()
1486 }
1487
1488 pub(crate) fn persisted_row_declared_field_missing(field_name: &str) -> Self {
1490 Self::persisted_row_field_decode_corruption(field_name)
1491 }
1492
1493 pub(crate) fn reverse_index_ordinal_overflow(
1495 _source_path: &str,
1496 _field_name: &str,
1497 _target_path: &str,
1498 _detail: impl Sized,
1499 ) -> Self {
1500 Self::index_internal()
1501 }
1502
1503 pub(crate) fn reverse_index_entry_corrupted(
1505 _source_path: &str,
1506 _field_name: &str,
1507 _target_path: &str,
1508 _index_key: impl fmt::Debug,
1509 _detail: impl Sized,
1510 ) -> Self {
1511 Self::index_corruption()
1512 }
1513
1514 pub(crate) fn relation_target_store_missing(
1516 _source_path: &str,
1517 _field_name: &str,
1518 _target_path: &str,
1519 _store_path: &str,
1520 _detail: impl Sized,
1521 ) -> Self {
1522 Self::executor_internal()
1523 }
1524
1525 pub(crate) fn relation_target_primary_key_arity_mismatch(
1527 expected_arity: usize,
1528 actual_arity: usize,
1529 ) -> Self {
1530 Self::with_diagnostic_facts(
1531 ErrorClass::Internal,
1532 ErrorOrigin::Executor,
1533 None,
1534 vec![
1535 (
1536 diagnostic_code::DiagnosticFactTag::ComponentKind,
1537 diagnostic_code::DiagnosticComponentKind::RelationTargetPrimaryKey.raw(),
1538 ),
1539 (
1540 diagnostic_code::DiagnosticFactTag::ExpectedArity,
1541 expected_arity as u64,
1542 ),
1543 (
1544 diagnostic_code::DiagnosticFactTag::ActualArity,
1545 actual_arity as u64,
1546 ),
1547 ],
1548 )
1549 }
1550
1551 pub(crate) fn relation_target_key_decode_failed(
1553 _context_label: &str,
1554 _source_path: &str,
1555 _field_name: &str,
1556 _target_path: &str,
1557 _detail: impl Sized,
1558 ) -> Self {
1559 Self::identity_corruption()
1560 }
1561
1562 pub(crate) fn relation_target_entity_mismatch(
1564 _context_label: &str,
1565 _source_path: &str,
1566 _field_name: &str,
1567 _target_path: &str,
1568 _target_entity_name: &str,
1569 expected_tag: u64,
1570 actual_tag: u64,
1571 ) -> Self {
1572 Self::with_diagnostic_facts(
1573 ErrorClass::Corruption,
1574 ErrorOrigin::Store,
1575 None,
1576 vec![
1577 (
1578 diagnostic_code::DiagnosticFactTag::ExpectedEntityTag,
1579 expected_tag,
1580 ),
1581 (
1582 diagnostic_code::DiagnosticFactTag::ActualEntityTag,
1583 actual_tag,
1584 ),
1585 ],
1586 )
1587 }
1588
1589 pub(crate) fn relation_source_row_decode_failed(
1591 _source_path: &str,
1592 _field_name: &str,
1593 _target_path: &str,
1594 _detail: impl Sized,
1595 ) -> Self {
1596 Self::persisted_row_decode_corruption()
1597 }
1598
1599 pub(crate) fn relation_source_row_unsupported_scalar_relation_key(
1601 _source_path: &str,
1602 _field_name: &str,
1603 _target_path: &str,
1604 ) -> Self {
1605 Self::persisted_row_decode_corruption()
1606 }
1607
1608 pub(crate) fn relation_source_row_unsupported_key_kind(_field_kind: impl fmt::Debug) -> Self {
1610 Self::persisted_row_decode_corruption()
1611 }
1612
1613 pub(crate) fn bytes_covering_component_payload_empty() -> Self {
1615 Self::index_corruption()
1616 }
1617
1618 pub(crate) fn bytes_covering_bool_payload_truncated() -> Self {
1620 Self::index_corruption()
1621 }
1622
1623 pub(crate) fn bytes_covering_component_payload_invalid_length() -> Self {
1625 Self::index_corruption()
1626 }
1627
1628 pub(crate) fn bytes_covering_bool_payload_invalid_value() -> Self {
1630 Self::index_corruption()
1631 }
1632
1633 pub(crate) fn bytes_covering_text_payload_invalid_terminator() -> Self {
1635 Self::index_corruption()
1636 }
1637
1638 pub(crate) fn bytes_covering_text_payload_trailing_bytes() -> Self {
1640 Self::index_corruption()
1641 }
1642
1643 pub(crate) fn bytes_covering_text_payload_invalid_utf8() -> Self {
1645 Self::index_corruption()
1646 }
1647
1648 pub(crate) fn bytes_covering_text_payload_invalid_escape_byte() -> Self {
1650 Self::index_corruption()
1651 }
1652
1653 pub(crate) fn bytes_covering_text_payload_missing_terminator() -> Self {
1655 Self::index_corruption()
1656 }
1657
1658 pub(crate) fn identity_corruption() -> Self {
1660 Self::new(ErrorClass::Corruption, ErrorOrigin::Identity)
1661 }
1662
1663 pub(crate) fn identity_state_corruption() -> Self {
1665 Self::identity_corruption()
1666 }
1667
1668 pub(crate) fn identity_state_conflict() -> Self {
1670 Self::new(ErrorClass::Conflict, ErrorOrigin::Identity)
1671 }
1672
1673 pub(crate) fn identity_state_capacity_exhausted() -> Self {
1675 Self::new(ErrorClass::Unsupported, ErrorOrigin::Identity)
1676 }
1677
1678 pub(crate) fn identity_exhausted() -> Self {
1680 Self::new(ErrorClass::Unsupported, ErrorOrigin::Identity)
1681 }
1682
1683 pub(crate) fn identity_candidate_count_exhausted() -> Self {
1685 Self::new(ErrorClass::Unsupported, ErrorOrigin::Identity)
1686 }
1687
1688 #[cold]
1690 #[inline(never)]
1691 pub(crate) fn store_unsupported() -> Self {
1692 Self::new(ErrorClass::Unsupported, ErrorOrigin::Store)
1693 }
1694
1695 pub(crate) fn schema_application_conflict() -> Self {
1697 Self::new(ErrorClass::Conflict, ErrorOrigin::Store)
1698 }
1699
1700 pub(crate) fn schema_migration(reason: diagnostic_code::SchemaMigrationCode) -> Self {
1702 let class = match reason.diagnostic_code() {
1703 diagnostic_code::DiagnosticCode::RuntimeConflict => ErrorClass::Conflict,
1704 diagnostic_code::DiagnosticCode::RuntimeCorruption => ErrorClass::Corruption,
1705 diagnostic_code::DiagnosticCode::RuntimeUnsupported => ErrorClass::Unsupported,
1706 _ => ErrorClass::Internal,
1707 };
1708 Self {
1709 class,
1710 origin: ErrorOrigin::Store,
1711 detail: Some(ErrorDetail::Store(StoreError::SchemaMigration { reason })),
1712 }
1713 }
1714
1715 pub(crate) fn schema_ddl_publication_race_lost(_entity_path: &str) -> Self {
1717 Self {
1718 class: ErrorClass::Unsupported,
1719 origin: ErrorOrigin::Store,
1720 detail: Some(ErrorDetail::Store(StoreError::SchemaDdlPublicationRaceLost)),
1721 }
1722 }
1723
1724 #[cfg(feature = "sql")]
1726 pub(crate) fn schema_ddl_rewrite_requires_migration(_entity_path: &str) -> Self {
1727 Self {
1728 class: ErrorClass::Unsupported,
1729 origin: ErrorOrigin::Store,
1730 detail: Some(ErrorDetail::Store(
1731 StoreError::SchemaDdlRewriteRequiresMigration,
1732 )),
1733 }
1734 }
1735
1736 pub(crate) fn journal_mutation_revision_exhausted() -> Self {
1738 Self {
1739 class: ErrorClass::Unsupported,
1740 origin: ErrorOrigin::Store,
1741 detail: Some(ErrorDetail::Store(
1742 StoreError::JournalMutationRevisionExhausted,
1743 )),
1744 }
1745 }
1746
1747 pub(crate) fn schema_transition_budget_exceeded(
1749 resource: SchemaTransitionBudgetResource,
1750 ) -> Self {
1751 Self {
1752 class: ErrorClass::Unsupported,
1753 origin: ErrorOrigin::Store,
1754 detail: Some(ErrorDetail::Store(
1755 StoreError::SchemaTransitionBudgetExceeded { resource },
1756 )),
1757 }
1758 }
1759
1760 pub(crate) fn unsupported_entity_tag_in_data_store(
1762 _entity_tag: crate::types::EntityTag,
1763 ) -> Self {
1764 Self::store_unsupported()
1765 }
1766
1767 #[cfg(not(test))]
1769 pub(crate) fn commit_memory_id_registration_failed(_err: impl Sized) -> Self {
1770 Self::store_internal()
1771 }
1772
1773 pub(crate) fn index_unsupported() -> Self {
1775 Self::new(ErrorClass::Unsupported, ErrorOrigin::Index)
1776 }
1777
1778 pub(crate) fn index_component_exceeds_max_size_at(
1780 entity_tag: u64,
1781 physical_generation: u64,
1782 component_index: usize,
1783 actual_length: usize,
1784 limit: usize,
1785 ) -> Self {
1786 Self::with_diagnostic_facts(
1787 ErrorClass::Unsupported,
1788 ErrorOrigin::Index,
1789 None,
1790 vec![
1791 (diagnostic_code::DiagnosticFactTag::EntityTag, entity_tag),
1792 (
1793 diagnostic_code::DiagnosticFactTag::PhysicalGeneration,
1794 physical_generation,
1795 ),
1796 (
1797 diagnostic_code::DiagnosticFactTag::ComponentIndex,
1798 component_index as u64,
1799 ),
1800 (
1801 diagnostic_code::DiagnosticFactTag::ComponentKind,
1802 diagnostic_code::DiagnosticComponentKind::IndexKeyComponent.raw(),
1803 ),
1804 (
1805 diagnostic_code::DiagnosticFactTag::ActualLength,
1806 actual_length as u64,
1807 ),
1808 (diagnostic_code::DiagnosticFactTag::Limit, limit as u64),
1809 ],
1810 )
1811 }
1812
1813 pub(crate) fn index_component_exceeds_max_size() -> Self {
1816 Self::index_unsupported()
1817 }
1818
1819 pub(crate) fn serialize_unsupported() -> Self {
1821 Self::new(ErrorClass::Unsupported, ErrorOrigin::Serialize)
1822 }
1823
1824 pub(crate) fn cursor_invalid_continuation() -> Self {
1826 Self::new(ErrorClass::Unsupported, ErrorOrigin::Cursor)
1827 }
1828
1829 pub(crate) fn serialize_incompatible_persisted_format() -> Self {
1831 Self::new(
1832 ErrorClass::IncompatiblePersistedFormat,
1833 ErrorOrigin::Serialize,
1834 )
1835 }
1836
1837 #[cfg(feature = "sql")]
1840 pub(crate) fn query_unsupported_sql_feature(feature: diagnostic_code::SqlFeatureCode) -> Self {
1841 Self {
1842 class: ErrorClass::Unsupported,
1843 origin: ErrorOrigin::Query,
1844 detail: Some(ErrorDetail::Query(
1845 QueryErrorDetail::UnsupportedSqlFeature { feature },
1846 )),
1847 }
1848 }
1849
1850 #[cfg(feature = "sql")]
1853 pub(crate) fn query_sql_lowering(reason: diagnostic_code::SqlLoweringCode) -> Self {
1854 Self {
1855 class: ErrorClass::Unsupported,
1856 origin: ErrorOrigin::Query,
1857 detail: Some(ErrorDetail::Query(QueryErrorDetail::SqlLowering { reason })),
1858 }
1859 }
1860
1861 #[cfg(feature = "sql")]
1863 pub(crate) fn query_sql_lowering_with_facts(
1864 reason: diagnostic_code::SqlLoweringCode,
1865 facts: Vec<(diagnostic_code::DiagnosticFactTag, u64)>,
1866 ) -> Self {
1867 Self::with_diagnostic_facts(
1868 ErrorClass::Unsupported,
1869 ErrorOrigin::Query,
1870 Some(diagnostic_code::DiagnosticDetail::SqlLowering { reason }),
1871 facts,
1872 )
1873 }
1874
1875 pub(crate) fn query_unsupported_projection(
1878 reason: diagnostic_code::QueryProjectionCode,
1879 ) -> Self {
1880 Self {
1881 class: ErrorClass::Unsupported,
1882 origin: ErrorOrigin::Query,
1883 detail: Some(ErrorDetail::Query(
1884 QueryErrorDetail::UnsupportedProjection { reason },
1885 )),
1886 }
1887 }
1888
1889 #[cfg(feature = "sql")]
1892 pub(crate) fn query_sql_surface_mismatch(
1893 mismatch: diagnostic_code::SqlSurfaceMismatchCode,
1894 ) -> Self {
1895 Self {
1896 class: ErrorClass::Unsupported,
1897 origin: ErrorOrigin::Query,
1898 detail: Some(ErrorDetail::Query(QueryErrorDetail::SqlSurfaceMismatch {
1899 mismatch,
1900 })),
1901 }
1902 }
1903
1904 pub(crate) fn query_sql_write_boundary(
1906 boundary: diagnostic_code::SqlWriteBoundaryCode,
1907 ) -> Self {
1908 Self {
1909 class: ErrorClass::Unsupported,
1910 origin: ErrorOrigin::Query,
1911 detail: Some(ErrorDetail::Query(QueryErrorDetail::SqlWriteBoundary {
1912 boundary,
1913 })),
1914 }
1915 }
1916
1917 pub(crate) fn query_sql_write_boundary_with_facts(
1919 boundary: diagnostic_code::SqlWriteBoundaryCode,
1920 facts: Vec<(diagnostic_code::DiagnosticFactTag, u64)>,
1921 ) -> Self {
1922 Self::with_diagnostic_facts(
1923 ErrorClass::Unsupported,
1924 ErrorOrigin::Query,
1925 Some(diagnostic_code::DiagnosticDetail::SqlWriteBoundary { boundary }),
1926 facts,
1927 )
1928 }
1929
1930 pub fn store_not_found(_key: impl Sized) -> Self {
1931 Self {
1932 class: ErrorClass::NotFound,
1933 origin: ErrorOrigin::Store,
1934 detail: Some(ErrorDetail::Store(StoreError::NotFound)),
1935 }
1936 }
1937
1938 pub fn unsupported_entity_path(_path: impl Sized) -> Self {
1940 Self::store_unsupported()
1941 }
1942
1943 #[cold]
1945 #[inline(never)]
1946 pub(crate) fn index_plan_corruption(origin: ErrorOrigin) -> Self {
1947 Self::new(ErrorClass::Corruption, origin)
1948 }
1949
1950 #[cold]
1952 #[inline(never)]
1953 pub(crate) fn index_plan_index_corruption() -> Self {
1954 Self::index_plan_corruption(ErrorOrigin::Index)
1955 }
1956
1957 #[cold]
1959 #[inline(never)]
1960 pub(crate) fn index_plan_store_corruption() -> Self {
1961 Self::index_plan_corruption(ErrorOrigin::Store)
1962 }
1963
1964 #[cold]
1966 #[inline(never)]
1967 pub(crate) fn index_plan_serialize_corruption() -> Self {
1968 Self::index_plan_corruption(ErrorOrigin::Serialize)
1969 }
1970
1971 #[cfg(test)]
1973 pub(crate) fn index_plan_invariant(origin: ErrorOrigin) -> Self {
1974 Self::new(ErrorClass::InvariantViolation, origin)
1975 }
1976
1977 #[cfg(test)]
1979 pub(crate) fn index_plan_store_invariant() -> Self {
1980 Self::index_plan_invariant(ErrorOrigin::Store)
1981 }
1982
1983 pub(crate) fn index_conflict() -> Self {
1989 Self::new(ErrorClass::Conflict, ErrorOrigin::Index)
1990 }
1991}
1992
1993impl From<diagnostic_code::QueryReadAdmissionCode> for InternalError {
1994 fn from(reason: diagnostic_code::QueryReadAdmissionCode) -> Self {
1995 Self {
1996 class: ErrorClass::Unsupported,
1997 origin: ErrorOrigin::Query,
1998 detail: Some(ErrorDetail::Query(QueryErrorDetail::QueryReadAdmission {
1999 reason,
2000 })),
2001 }
2002 }
2003}
2004
2005impl fmt::Debug for InternalError {
2006 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2007 fmt_compact_diagnostic(
2008 f,
2009 self.diagnostic_code(),
2010 self.detail
2011 .as_ref()
2012 .and_then(ErrorDetail::diagnostic_detail),
2013 )
2014 }
2015}
2016
2017impl fmt::Display for InternalError {
2018 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2019 f.write_str(self.message())
2020 }
2021}
2022
2023impl std::error::Error for InternalError {}
2024
2025#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq)]
2034pub enum ConstraintValuePathComponent {
2035 RootField { field_id: u32 },
2037
2038 RecordMember {
2040 composite_type_id: u32,
2041 member_id: u32,
2042 },
2043
2044 TupleElement {
2046 composite_type_id: u32,
2047 ordinal: u32,
2048 },
2049
2050 Newtype { composite_type_id: u32 },
2052
2053 EnumVariant { enum_type_id: u32, variant_id: u32 },
2055
2056 ListElement { index: u32 },
2058
2059 SetElement { index: u32 },
2061
2062 MapEntryKey { index: u32 },
2064
2065 MapEntryValue { index: u32 },
2067}
2068
2069impl fmt::Display for ConstraintValuePathComponent {
2070 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2071 match self {
2072 Self::RootField { field_id } => write!(f, "field#{field_id}"),
2073 Self::RecordMember {
2074 composite_type_id,
2075 member_id,
2076 } => write!(f, "record#{composite_type_id}.member#{member_id}"),
2077 Self::TupleElement {
2078 composite_type_id,
2079 ordinal,
2080 } => write!(f, "tuple#{composite_type_id}[{ordinal}]"),
2081 Self::Newtype { composite_type_id } => write!(f, "newtype#{composite_type_id}"),
2082 Self::EnumVariant {
2083 enum_type_id,
2084 variant_id,
2085 } => write!(f, "enum#{enum_type_id}.variant#{variant_id}"),
2086 Self::ListElement { index } => write!(f, "list[{index}]"),
2087 Self::SetElement { index } => write!(f, "set[{index}]"),
2088 Self::MapEntryKey { index } => write!(f, "map[{index}].key"),
2089 Self::MapEntryValue { index } => write!(f, "map[{index}].value"),
2090 }
2091 }
2092}
2093
2094#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
2101pub struct ConstraintValuePath {
2102 components: Vec<ConstraintValuePathComponent>,
2103}
2104
2105impl ConstraintValuePath {
2106 #[must_use]
2108 pub(crate) const fn new(components: Vec<ConstraintValuePathComponent>) -> Self {
2109 Self { components }
2110 }
2111
2112 #[must_use]
2114 pub const fn components(&self) -> &[ConstraintValuePathComponent] {
2115 self.components.as_slice()
2116 }
2117}
2118
2119impl fmt::Display for ConstraintValuePath {
2120 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2121 for (ordinal, component) in self.components.iter().enumerate() {
2122 if ordinal != 0 {
2123 f.write_str("/")?;
2124 }
2125 component.fmt(f)?;
2126 }
2127 Ok(())
2128 }
2129}
2130
2131#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
2140pub struct ConstraintValidationFindingOutput {
2141 accepted_schema_fingerprint: [u8; 16],
2142 entity_tag: u64,
2143 constraint_id: u32,
2144 primary_key: Vec<u8>,
2145 field_ids: Vec<u32>,
2146 value_path: Option<ConstraintValuePath>,
2147 error_code: u16,
2148}
2149
2150impl ConstraintValidationFindingOutput {
2151 #[must_use]
2153 pub(crate) const fn new(
2154 accepted_schema_fingerprint: [u8; 16],
2155 entity_tag: u64,
2156 constraint_id: u32,
2157 primary_key: Vec<u8>,
2158 field_ids: Vec<u32>,
2159 value_path: Option<ConstraintValuePath>,
2160 error_code: u16,
2161 ) -> Self {
2162 Self {
2163 accepted_schema_fingerprint,
2164 entity_tag,
2165 constraint_id,
2166 primary_key,
2167 field_ids,
2168 value_path,
2169 error_code,
2170 }
2171 }
2172
2173 #[must_use]
2175 pub const fn accepted_schema_fingerprint(&self) -> [u8; 16] {
2176 self.accepted_schema_fingerprint
2177 }
2178
2179 #[must_use]
2181 pub const fn entity_tag(&self) -> u64 {
2182 self.entity_tag
2183 }
2184
2185 #[must_use]
2187 pub const fn constraint_id(&self) -> u32 {
2188 self.constraint_id
2189 }
2190
2191 #[must_use]
2193 pub const fn primary_key(&self) -> &[u8] {
2194 self.primary_key.as_slice()
2195 }
2196
2197 #[must_use]
2199 pub const fn field_ids(&self) -> &[u32] {
2200 self.field_ids.as_slice()
2201 }
2202
2203 #[must_use]
2205 pub const fn value_path(&self) -> Option<&ConstraintValuePath> {
2206 self.value_path.as_ref()
2207 }
2208
2209 #[must_use]
2211 pub const fn error_code(&self) -> diagnostic_code::ErrorCode {
2212 diagnostic_code::ErrorCode::from_raw(self.error_code)
2213 }
2214
2215 #[must_use]
2217 pub const fn error_class(&self) -> diagnostic_code::ErrorClass {
2218 self.error_code().class()
2219 }
2220}
2221
2222#[derive(Clone)]
2224pub(crate) struct AcceptedConstraintFactContext {
2225 fingerprint_method: u8,
2226 accepted_schema_fingerprint: [u8; 16],
2227 entity_tag: u64,
2228 constraint_id: u32,
2229 constraint_kind: diagnostic_code::DiagnosticConstraintKind,
2230 mutation: Option<MutationDiagnosticContext>,
2231 value_path: Option<ConstraintValuePath>,
2232}
2233
2234impl AcceptedConstraintFactContext {
2235 #[must_use]
2236 pub(crate) fn write_admission(
2237 fingerprint_method: u8,
2238 accepted_schema_fingerprint: [u8; 16],
2239 entity_tag: u64,
2240 constraint_id: u32,
2241 constraint_kind: diagnostic_code::DiagnosticConstraintKind,
2242 mutation: Option<MutationDiagnosticContext>,
2243 value_path: Option<ConstraintValuePath>,
2244 ) -> Self {
2245 debug_assert!(mutation.is_none_or(|context| context.entity_tag() == entity_tag));
2246 Self {
2247 fingerprint_method,
2248 accepted_schema_fingerprint,
2249 entity_tag,
2250 constraint_id,
2251 constraint_kind,
2252 mutation,
2253 value_path,
2254 }
2255 }
2256
2257 fn facts(self) -> Vec<(diagnostic_code::DiagnosticFactTag, u64)> {
2258 let high = u64::from_be_bytes([
2259 self.accepted_schema_fingerprint[0],
2260 self.accepted_schema_fingerprint[1],
2261 self.accepted_schema_fingerprint[2],
2262 self.accepted_schema_fingerprint[3],
2263 self.accepted_schema_fingerprint[4],
2264 self.accepted_schema_fingerprint[5],
2265 self.accepted_schema_fingerprint[6],
2266 self.accepted_schema_fingerprint[7],
2267 ]);
2268 let low = u64::from_be_bytes([
2269 self.accepted_schema_fingerprint[8],
2270 self.accepted_schema_fingerprint[9],
2271 self.accepted_schema_fingerprint[10],
2272 self.accepted_schema_fingerprint[11],
2273 self.accepted_schema_fingerprint[12],
2274 self.accepted_schema_fingerprint[13],
2275 self.accepted_schema_fingerprint[14],
2276 self.accepted_schema_fingerprint[15],
2277 ]);
2278 let path_len = self
2279 .value_path
2280 .as_ref()
2281 .map_or(0, |path| path.components().len());
2282 let mutation_fact_count = self.mutation.map_or(0, |mutation| {
2283 1 + usize::from(mutation.batch_position.is_some())
2284 });
2285 let mut facts = Vec::with_capacity(7 + mutation_fact_count + path_len);
2286 facts.push((
2287 diagnostic_code::DiagnosticFactTag::AcceptedSchemaFingerprintMethod,
2288 u64::from(self.fingerprint_method),
2289 ));
2290 facts.push((
2291 diagnostic_code::DiagnosticFactTag::AcceptedSchemaFingerprintHigh,
2292 high,
2293 ));
2294 facts.push((
2295 diagnostic_code::DiagnosticFactTag::AcceptedSchemaFingerprintLow,
2296 low,
2297 ));
2298 facts.push((
2299 diagnostic_code::DiagnosticFactTag::EntityTag,
2300 self.entity_tag,
2301 ));
2302 facts.push((
2303 diagnostic_code::DiagnosticFactTag::ConstraintId,
2304 u64::from(self.constraint_id),
2305 ));
2306 facts.push((
2307 diagnostic_code::DiagnosticFactTag::ConstraintKind,
2308 self.constraint_kind.raw(),
2309 ));
2310 facts.push((
2311 diagnostic_code::DiagnosticFactTag::ConstraintContext,
2312 diagnostic_code::DiagnosticConstraintContext::WriteAdmission.raw(),
2313 ));
2314 if let Some(mutation) = self.mutation {
2315 mutation.append_operation_facts(&mut facts);
2316 }
2317 if let Some(path) = self.value_path {
2318 for component in path.components {
2319 facts.push(constraint_value_path_fact(component));
2320 }
2321 }
2322 debug_assert!(facts.len() <= diagnostic_code::MAX_PUBLIC_DIAGNOSTIC_FACTS);
2323 facts
2324 }
2325}
2326
2327fn constraint_value_path_fact(
2328 component: ConstraintValuePathComponent,
2329) -> (diagnostic_code::DiagnosticFactTag, u64) {
2330 use diagnostic_code::DiagnosticFactTag;
2331 match component {
2332 ConstraintValuePathComponent::RootField { field_id } => {
2333 (DiagnosticFactTag::RootField, u64::from(field_id))
2334 }
2335 ConstraintValuePathComponent::RecordMember {
2336 composite_type_id,
2337 member_id,
2338 } => (
2339 DiagnosticFactTag::RecordMember,
2340 diagnostic_code::pack_u32_pair(composite_type_id, member_id),
2341 ),
2342 ConstraintValuePathComponent::TupleElement {
2343 composite_type_id,
2344 ordinal,
2345 } => (
2346 DiagnosticFactTag::TupleElement,
2347 diagnostic_code::pack_u32_pair(composite_type_id, ordinal),
2348 ),
2349 ConstraintValuePathComponent::Newtype { composite_type_id } => {
2350 (DiagnosticFactTag::Newtype, u64::from(composite_type_id))
2351 }
2352 ConstraintValuePathComponent::EnumVariant {
2353 enum_type_id,
2354 variant_id,
2355 } => (
2356 DiagnosticFactTag::EnumVariant,
2357 diagnostic_code::pack_u32_pair(enum_type_id, variant_id),
2358 ),
2359 ConstraintValuePathComponent::ListElement { index } => {
2360 (DiagnosticFactTag::ListElement, u64::from(index))
2361 }
2362 ConstraintValuePathComponent::SetElement { index } => {
2363 (DiagnosticFactTag::SetElement, u64::from(index))
2364 }
2365 ConstraintValuePathComponent::MapEntryKey { index } => {
2366 (DiagnosticFactTag::MapEntryKey, u64::from(index))
2367 }
2368 ConstraintValuePathComponent::MapEntryValue { index } => {
2369 (DiagnosticFactTag::MapEntryValue, u64::from(index))
2370 }
2371 }
2372}
2373
2374pub enum ErrorDetail {
2382 DiagnosticFacts(Box<DiagnosticFactDetail>),
2384 Executor(ExecutorErrorDetail),
2386 Store(StoreError),
2387 Query(QueryErrorDetail),
2388 Recovery(RecoveryErrorDetail),
2389 }
2392
2393pub enum ExecutorErrorDetail {
2395 MutationRequiredFieldMissing,
2397 MutationManagedTimestampRegression,
2399 MutationDatabaseOwnedFieldExplicit,
2401 MutationBatchEmpty,
2403 MutationBatchTooManyItems,
2405 MutationBatchStagedBytesExceeded,
2407 MutationBatchResultBytesExceeded,
2409 MutationBatchStoreMismatch,
2411 MutationBatchTooManyEntities,
2413 MutationBatchDuplicateKey,
2415 AcceptedRowConstraintProgramCorrupt,
2417}
2418
2419pub enum RecoveryErrorDetail {
2426 UnsupportedFormatVersion { found: Option<u16>, required: u16 },
2427
2428 MalformedFormatMarker { reason: RecoveryFormatMarkerError },
2429}
2430
2431#[derive(Clone, Copy, Eq, PartialEq)]
2433pub enum RecoveryFormatMarkerError {
2434 Magic,
2435 Checksum,
2436 State,
2437}
2438
2439impl RecoveryFormatMarkerError {
2440 const fn diagnostic_decode_reason(self) -> diagnostic_code::DiagnosticDecodeReason {
2441 match self {
2442 Self::Magic => diagnostic_code::DiagnosticDecodeReason::RecoveryMarkerMagic,
2443 Self::Checksum => diagnostic_code::DiagnosticDecodeReason::RecoveryMarkerChecksum,
2444 Self::State => diagnostic_code::DiagnosticDecodeReason::RecoveryMarkerState,
2445 }
2446 }
2447}
2448
2449pub enum StoreError {
2457 NotFound,
2458
2459 Corrupt,
2460
2461 InvariantViolation,
2462
2463 SchemaDdlPublicationRaceLost,
2464
2465 SchemaDdlRewriteRequiresMigration,
2466
2467 SchemaMigration {
2468 reason: diagnostic_code::SchemaMigrationCode,
2469 },
2470
2471 SchemaRowLayoutVersionExhausted,
2472
2473 JournalMutationRevisionExhausted,
2474
2475 SchemaTransitionBudgetExceeded {
2476 resource: SchemaTransitionBudgetResource,
2477 },
2478
2479 SchemaGeneratedFieldAfterDdlField,
2481
2482 SchemaGeneratedConstraintActivationStale,
2484}
2485
2486pub enum QueryErrorDetail {
2493 NumericOverflow,
2494
2495 NumericNotRepresentable,
2496
2497 UnsupportedSqlFeature {
2498 feature: diagnostic_code::SqlFeatureCode,
2499 },
2500
2501 SqlLowering {
2502 reason: diagnostic_code::SqlLoweringCode,
2503 },
2504
2505 UnsupportedProjection {
2506 reason: diagnostic_code::QueryProjectionCode,
2507 },
2508
2509 UnknownAggregateTargetField,
2510
2511 ResultShapeMismatch {
2512 reason: diagnostic_code::QueryResultShapeCode,
2513 },
2514
2515 QueryReadAdmission {
2516 reason: diagnostic_code::QueryReadAdmissionCode,
2517 },
2518
2519 SqlSurfaceMismatch {
2520 mismatch: diagnostic_code::SqlSurfaceMismatchCode,
2521 },
2522
2523 SqlWriteBoundary {
2524 boundary: diagnostic_code::SqlWriteBoundaryCode,
2525 },
2526
2527 SchemaDdlAdmission {
2528 error: SchemaDdlAdmissionError,
2529 },
2530
2531 StaleSchemaRevision,
2532}
2533
2534impl fmt::Display for QueryErrorDetail {
2535 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2536 f.write_str(COMPACT_QUERY_DIAGNOSTIC_MESSAGE)
2537 }
2538}
2539
2540impl std::error::Error for QueryErrorDetail {}
2541
2542#[derive(Clone, Copy, Debug, Eq, PartialEq)]
2550pub enum SchemaTransitionBudgetResource {
2551 DeletionKeys,
2553 ProjectionEntries,
2555 ProjectionWorkUnits,
2557 SourceRows,
2559 SourceRowBytes,
2561 StagedRawBytes,
2563}
2564
2565#[derive(Clone, Copy, Eq, PartialEq)]
2574pub enum SchemaDdlAdmissionError {
2575 MissingExpectedSchemaVersion,
2576
2577 MissingNextSchemaVersion,
2578
2579 StaleExpectedSchemaVersion,
2580
2581 InvalidExpectedSchemaVersion,
2582
2583 InvalidNextSchemaVersion,
2584
2585 AcceptedSchemaChangeWithoutVersionBump,
2586
2587 EmptyVersionBump,
2588
2589 VersionGap,
2590
2591 VersionRollback,
2592
2593 FingerprintMethodMismatch,
2594
2595 UnsupportedTransitionClass,
2596
2597 PhysicalRunnerMissing,
2598
2599 ValidationFailed,
2600
2601 PublicationRaceLost,
2602
2603 InvalidAddColumnDefault,
2604
2605 InvalidAlterColumnDefault,
2606
2607 RowLayoutVersionExhausted,
2608
2609 GeneratedIndexDropRejected,
2610
2611 SchemaRewriteRequiresMigration,
2612
2613 SchemaTransitionBudgetExceeded {
2614 resource: SchemaTransitionBudgetResource,
2615 },
2616
2617 GeneratedFieldDefaultChangeRejected,
2618
2619 GeneratedFieldNullabilityChangeRejected,
2620}
2621
2622impl fmt::Display for SchemaDdlAdmissionError {
2623 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2624 f.write_str(COMPACT_QUERY_DIAGNOSTIC_MESSAGE)
2625 }
2626}
2627
2628impl std::error::Error for SchemaDdlAdmissionError {}
2629
2630impl fmt::Debug for ErrorDetail {
2631 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2632 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2633 }
2634}
2635
2636impl fmt::Debug for ExecutorErrorDetail {
2637 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2638 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2639 }
2640}
2641
2642impl fmt::Debug for StoreError {
2643 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2644 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2645 }
2646}
2647
2648impl fmt::Debug for QueryErrorDetail {
2649 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2650 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2651 }
2652}
2653
2654impl fmt::Debug for RecoveryErrorDetail {
2655 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2656 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2657 }
2658}
2659
2660impl fmt::Debug for RecoveryFormatMarkerError {
2661 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2662 fmt_compact_diagnostic(
2663 f,
2664 diagnostic_code::DiagnosticCode::RuntimeCorruption,
2665 Some(diagnostic_code::DiagnosticDetail::RuntimeKind {
2666 kind: diagnostic_code::RuntimeErrorKind::Corruption,
2667 }),
2668 )
2669 }
2670}
2671
2672impl fmt::Debug for SchemaDdlAdmissionError {
2673 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2674 fmt_compact_diagnostic(
2675 f,
2676 diagnostic_code::DiagnosticCode::SchemaDdlAdmission,
2677 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2678 reason: self.diagnostic_code(),
2679 }),
2680 )
2681 }
2682}
2683
2684fn fmt_compact_diagnostic(
2685 f: &mut fmt::Formatter<'_>,
2686 code: diagnostic_code::DiagnosticCode,
2687 detail: Option<diagnostic_code::DiagnosticDetail>,
2688) -> fmt::Result {
2689 write!(
2690 f,
2691 "{}",
2692 diagnostic_code::ErrorCode::from_parts(code, detail).raw()
2693 )
2694}
2695
2696impl ErrorDetail {
2697 #[must_use]
2699 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2700 match self {
2701 Self::DiagnosticFacts(detail) => detail.diagnostic.code(),
2702 Self::Executor(error) => error.diagnostic_code(),
2703 Self::Store(error) => error.diagnostic_code(),
2704 Self::Query(error) => error.diagnostic_code(),
2705 Self::Recovery(error) => error.diagnostic_code(),
2706 }
2707 }
2708
2709 #[must_use]
2711 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2712 match self {
2713 Self::DiagnosticFacts(detail) => detail.diagnostic.detail().copied(),
2714 Self::Executor(error) => error.diagnostic_detail(),
2715 Self::Store(error) => error.diagnostic_detail(),
2716 Self::Query(error) => error.diagnostic_detail(),
2717 Self::Recovery(error) => error.diagnostic_detail(),
2718 }
2719 }
2720
2721 #[must_use]
2723 #[cold]
2724 #[inline(never)]
2725 pub fn diagnostic_facts(&self) -> Vec<(diagnostic_code::DiagnosticFactTag, u64)> {
2726 match self {
2727 Self::DiagnosticFacts(detail) => detail.facts.clone(),
2728 Self::Executor(error) => error.diagnostic_facts(),
2729 Self::Query(error) => error.diagnostic_facts(),
2730 Self::Recovery(error) => error.diagnostic_facts(),
2731 Self::Store(_) => Vec::new(),
2732 }
2733 }
2734}
2735
2736impl ExecutorErrorDetail {
2737 #[must_use]
2739 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2740 match self {
2741 Self::MutationRequiredFieldMissing
2742 | Self::MutationDatabaseOwnedFieldExplicit
2743 | Self::MutationBatchEmpty
2744 | Self::MutationBatchTooManyItems
2745 | Self::MutationBatchTooManyEntities
2746 | Self::MutationBatchStagedBytesExceeded
2747 | Self::MutationBatchResultBytesExceeded => {
2748 diagnostic_code::DiagnosticCode::RuntimeUnsupported
2749 }
2750 Self::MutationBatchStoreMismatch | Self::MutationBatchDuplicateKey => {
2751 diagnostic_code::DiagnosticCode::RuntimeConflict
2752 }
2753 Self::MutationManagedTimestampRegression => {
2754 diagnostic_code::DiagnosticCode::RuntimeInvariantViolation
2755 }
2756 Self::AcceptedRowConstraintProgramCorrupt => {
2757 diagnostic_code::DiagnosticCode::RuntimeCorruption
2758 }
2759 }
2760 }
2761
2762 #[must_use]
2764 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2765 match self {
2766 Self::MutationRequiredFieldMissing => {
2767 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2768 boundary: diagnostic_code::RuntimeBoundaryCode::MutationRequiredFieldMissing,
2769 })
2770 }
2771 Self::MutationDatabaseOwnedFieldExplicit => {
2772 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2773 boundary:
2774 diagnostic_code::RuntimeBoundaryCode::MutationDatabaseOwnedFieldExplicit,
2775 })
2776 }
2777 Self::MutationBatchEmpty => Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2778 boundary: diagnostic_code::RuntimeBoundaryCode::MutationBatchEmpty,
2779 }),
2780 Self::MutationBatchTooManyItems => {
2781 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2782 boundary: diagnostic_code::RuntimeBoundaryCode::MutationBatchTooManyItems,
2783 })
2784 }
2785 Self::MutationBatchStagedBytesExceeded => {
2786 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2787 boundary:
2788 diagnostic_code::RuntimeBoundaryCode::MutationBatchStagedBytesExceeded,
2789 })
2790 }
2791 Self::MutationBatchResultBytesExceeded => {
2792 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2793 boundary:
2794 diagnostic_code::RuntimeBoundaryCode::MutationBatchResultBytesExceeded,
2795 })
2796 }
2797 Self::MutationBatchStoreMismatch => {
2798 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2799 boundary: diagnostic_code::RuntimeBoundaryCode::MutationBatchStoreMismatch,
2800 })
2801 }
2802 Self::MutationBatchTooManyEntities => {
2803 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2804 boundary: diagnostic_code::RuntimeBoundaryCode::MutationBatchTooManyEntities,
2805 })
2806 }
2807 Self::MutationBatchDuplicateKey => {
2808 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2809 boundary: diagnostic_code::RuntimeBoundaryCode::MutationBatchDuplicateKey,
2810 })
2811 }
2812 Self::MutationManagedTimestampRegression => {
2813 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2814 boundary:
2815 diagnostic_code::RuntimeBoundaryCode::MutationManagedTimestampRegression,
2816 })
2817 }
2818 Self::AcceptedRowConstraintProgramCorrupt => {
2819 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2820 boundary:
2821 diagnostic_code::RuntimeBoundaryCode::AcceptedRowConstraintProgramCorrupt,
2822 })
2823 }
2824 }
2825 }
2826
2827 #[must_use]
2829 #[cold]
2830 #[inline(never)]
2831 pub const fn diagnostic_facts(&self) -> Vec<(diagnostic_code::DiagnosticFactTag, u64)> {
2832 Vec::new()
2833 }
2834}
2835
2836impl RecoveryErrorDetail {
2837 #[must_use]
2839 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2840 match self {
2841 Self::UnsupportedFormatVersion { .. } => {
2842 diagnostic_code::DiagnosticCode::RuntimeIncompatiblePersistedFormat
2843 }
2844 Self::MalformedFormatMarker { .. } => {
2845 diagnostic_code::DiagnosticCode::RuntimeCorruption
2846 }
2847 }
2848 }
2849
2850 #[must_use]
2852 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2853 let kind = match self {
2854 Self::UnsupportedFormatVersion { .. } => {
2855 diagnostic_code::RuntimeErrorKind::IncompatiblePersistedFormat
2856 }
2857 Self::MalformedFormatMarker { .. } => diagnostic_code::RuntimeErrorKind::Corruption,
2858 };
2859
2860 Some(diagnostic_code::DiagnosticDetail::RuntimeKind { kind })
2861 }
2862
2863 #[must_use]
2865 pub fn diagnostic_facts(&self) -> Vec<(diagnostic_code::DiagnosticFactTag, u64)> {
2866 match self {
2867 Self::UnsupportedFormatVersion { found, required } => {
2868 let mut facts = Vec::with_capacity(usize::from(found.is_some()) + 1);
2869 facts.push((
2870 diagnostic_code::DiagnosticFactTag::ExpectedVersion,
2871 u64::from(*required),
2872 ));
2873 if let Some(found) = found {
2874 facts.push((
2875 diagnostic_code::DiagnosticFactTag::ActualVersion,
2876 u64::from(*found),
2877 ));
2878 }
2879 facts
2880 }
2881 Self::MalformedFormatMarker { reason } => vec![(
2882 diagnostic_code::DiagnosticFactTag::DecodeReason,
2883 reason.diagnostic_decode_reason().raw(),
2884 )],
2885 }
2886 }
2887}
2888
2889impl StoreError {
2890 #[must_use]
2892 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2893 match self {
2894 Self::NotFound => diagnostic_code::DiagnosticCode::StoreNotFound,
2895 Self::Corrupt => diagnostic_code::DiagnosticCode::StoreCorruption,
2896 Self::InvariantViolation => diagnostic_code::DiagnosticCode::StoreInvariantViolation,
2897 Self::SchemaDdlPublicationRaceLost
2898 | Self::SchemaDdlRewriteRequiresMigration
2899 | Self::SchemaRowLayoutVersionExhausted
2900 | Self::SchemaTransitionBudgetExceeded { .. } => {
2901 diagnostic_code::DiagnosticCode::SchemaDdlAdmission
2902 }
2903 Self::JournalMutationRevisionExhausted | Self::SchemaGeneratedFieldAfterDdlField => {
2904 diagnostic_code::DiagnosticCode::RuntimeUnsupported
2905 }
2906 Self::SchemaGeneratedConstraintActivationStale => {
2907 diagnostic_code::DiagnosticCode::RuntimeConflict
2908 }
2909 Self::SchemaMigration { reason } => reason.diagnostic_code(),
2910 }
2911 }
2912
2913 #[must_use]
2915 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2916 match self {
2917 Self::SchemaDdlPublicationRaceLost => {
2918 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2919 reason: diagnostic_code::SchemaDdlAdmissionCode::PublicationRaceLost,
2920 })
2921 }
2922 Self::SchemaDdlRewriteRequiresMigration => {
2923 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2924 reason: diagnostic_code::SchemaDdlAdmissionCode::SchemaRewriteRequiresMigration,
2925 })
2926 }
2927 Self::SchemaMigration { reason } => {
2928 Some(diagnostic_code::DiagnosticDetail::SchemaMigration { reason: *reason })
2929 }
2930 Self::SchemaRowLayoutVersionExhausted => {
2931 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2932 reason: diagnostic_code::SchemaDdlAdmissionCode::RowLayoutVersionExhausted,
2933 })
2934 }
2935 Self::JournalMutationRevisionExhausted => {
2936 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2937 boundary:
2938 diagnostic_code::RuntimeBoundaryCode::JournalMutationRevisionExhausted,
2939 })
2940 }
2941 Self::SchemaTransitionBudgetExceeded { .. } => {
2942 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2943 reason: diagnostic_code::SchemaDdlAdmissionCode::SchemaTransitionBudgetExceeded,
2944 })
2945 }
2946 Self::SchemaGeneratedFieldAfterDdlField => {
2947 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2948 boundary: diagnostic_code::RuntimeBoundaryCode::GeneratedFieldAfterDdlField,
2949 })
2950 }
2951 Self::SchemaGeneratedConstraintActivationStale => {
2952 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2953 boundary:
2954 diagnostic_code::RuntimeBoundaryCode::GeneratedConstraintActivationStale,
2955 })
2956 }
2957 Self::NotFound | Self::Corrupt | Self::InvariantViolation => None,
2958 }
2959 }
2960}
2961
2962impl QueryErrorDetail {
2963 #[must_use]
2965 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2966 match self {
2967 Self::NumericOverflow => diagnostic_code::DiagnosticCode::QueryNumericOverflow,
2968 Self::NumericNotRepresentable => {
2969 diagnostic_code::DiagnosticCode::QueryNumericNotRepresentable
2970 }
2971 Self::UnsupportedSqlFeature { .. } => {
2972 diagnostic_code::DiagnosticCode::QueryUnsupportedSqlFeature
2973 }
2974 Self::SqlLowering { .. } => diagnostic_code::DiagnosticCode::QueryUnsupportedSqlFeature,
2975 Self::UnsupportedProjection { .. } => {
2976 diagnostic_code::DiagnosticCode::QueryUnsupportedProjection
2977 }
2978 Self::UnknownAggregateTargetField => {
2979 diagnostic_code::DiagnosticCode::QueryUnknownAggregateTargetField
2980 }
2981 Self::ResultShapeMismatch { .. } => {
2982 diagnostic_code::DiagnosticCode::QueryResultShapeMismatch
2983 }
2984 Self::QueryReadAdmission { .. } => diagnostic_code::DiagnosticCode::QueryReadAdmission,
2985 Self::SqlSurfaceMismatch { .. } => {
2986 diagnostic_code::DiagnosticCode::QuerySqlSurfaceMismatch
2987 }
2988 Self::SqlWriteBoundary { .. } => diagnostic_code::DiagnosticCode::QuerySqlWriteBoundary,
2989 Self::SchemaDdlAdmission { .. } => diagnostic_code::DiagnosticCode::SchemaDdlAdmission,
2990 Self::StaleSchemaRevision => diagnostic_code::DiagnosticCode::RuntimeConflict,
2991 }
2992 }
2993
2994 #[must_use]
2996 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2997 match self {
2998 Self::UnsupportedSqlFeature { feature } => {
2999 Some(diagnostic_code::DiagnosticDetail::UnsupportedSqlFeature { feature: *feature })
3000 }
3001 Self::SqlLowering { reason } => {
3002 Some(diagnostic_code::DiagnosticDetail::SqlLowering { reason: *reason })
3003 }
3004 Self::UnsupportedProjection { reason } => {
3005 Some(diagnostic_code::DiagnosticDetail::QueryProjection { reason: *reason })
3006 }
3007 Self::ResultShapeMismatch { reason } => {
3008 Some(diagnostic_code::DiagnosticDetail::QueryResultShape { reason: *reason })
3009 }
3010 Self::QueryReadAdmission { reason } => {
3011 Some(diagnostic_code::DiagnosticDetail::QueryReadAdmission { reason: *reason })
3012 }
3013 Self::SqlSurfaceMismatch { mismatch } => {
3014 Some(diagnostic_code::DiagnosticDetail::SqlSurfaceMismatch {
3015 mismatch: *mismatch,
3016 })
3017 }
3018 Self::SqlWriteBoundary { boundary } => {
3019 Some(diagnostic_code::DiagnosticDetail::SqlWriteBoundary {
3020 boundary: *boundary,
3021 })
3022 }
3023 Self::SchemaDdlAdmission { error } => {
3024 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
3025 reason: error.diagnostic_code(),
3026 })
3027 }
3028 Self::NumericOverflow
3029 | Self::NumericNotRepresentable
3030 | Self::UnknownAggregateTargetField
3031 | Self::StaleSchemaRevision => None,
3032 }
3033 }
3034
3035 #[must_use]
3037 #[cold]
3038 #[inline(never)]
3039 pub const fn diagnostic_facts(&self) -> Vec<(diagnostic_code::DiagnosticFactTag, u64)> {
3040 Vec::new()
3041 }
3042}
3043
3044impl SchemaDdlAdmissionError {
3045 #[must_use]
3047 pub const fn diagnostic_code(&self) -> diagnostic_code::SchemaDdlAdmissionCode {
3048 match self {
3049 Self::MissingExpectedSchemaVersion => {
3050 diagnostic_code::SchemaDdlAdmissionCode::MissingExpectedSchemaVersion
3051 }
3052 Self::MissingNextSchemaVersion => {
3053 diagnostic_code::SchemaDdlAdmissionCode::MissingNextSchemaVersion
3054 }
3055 Self::StaleExpectedSchemaVersion => {
3056 diagnostic_code::SchemaDdlAdmissionCode::StaleExpectedSchemaVersion
3057 }
3058 Self::InvalidExpectedSchemaVersion => {
3059 diagnostic_code::SchemaDdlAdmissionCode::InvalidExpectedSchemaVersion
3060 }
3061 Self::InvalidNextSchemaVersion => {
3062 diagnostic_code::SchemaDdlAdmissionCode::InvalidNextSchemaVersion
3063 }
3064 Self::AcceptedSchemaChangeWithoutVersionBump => {
3065 diagnostic_code::SchemaDdlAdmissionCode::AcceptedSchemaChangeWithoutVersionBump
3066 }
3067 Self::EmptyVersionBump => diagnostic_code::SchemaDdlAdmissionCode::EmptyVersionBump,
3068 Self::VersionGap => diagnostic_code::SchemaDdlAdmissionCode::VersionGap,
3069 Self::VersionRollback => diagnostic_code::SchemaDdlAdmissionCode::VersionRollback,
3070 Self::FingerprintMethodMismatch => {
3071 diagnostic_code::SchemaDdlAdmissionCode::FingerprintMethodMismatch
3072 }
3073 Self::UnsupportedTransitionClass => {
3074 diagnostic_code::SchemaDdlAdmissionCode::UnsupportedTransitionClass
3075 }
3076 Self::PhysicalRunnerMissing => {
3077 diagnostic_code::SchemaDdlAdmissionCode::PhysicalRunnerMissing
3078 }
3079 Self::ValidationFailed => diagnostic_code::SchemaDdlAdmissionCode::ValidationFailed,
3080 Self::PublicationRaceLost => {
3081 diagnostic_code::SchemaDdlAdmissionCode::PublicationRaceLost
3082 }
3083 Self::InvalidAddColumnDefault => {
3084 diagnostic_code::SchemaDdlAdmissionCode::InvalidAddColumnDefault
3085 }
3086 Self::InvalidAlterColumnDefault => {
3087 diagnostic_code::SchemaDdlAdmissionCode::InvalidAlterColumnDefault
3088 }
3089 Self::GeneratedIndexDropRejected => {
3090 diagnostic_code::SchemaDdlAdmissionCode::GeneratedIndexDropRejected
3091 }
3092 Self::SchemaRewriteRequiresMigration => {
3093 diagnostic_code::SchemaDdlAdmissionCode::SchemaRewriteRequiresMigration
3094 }
3095 Self::SchemaTransitionBudgetExceeded { .. } => {
3096 diagnostic_code::SchemaDdlAdmissionCode::SchemaTransitionBudgetExceeded
3097 }
3098 Self::GeneratedFieldDefaultChangeRejected => {
3099 diagnostic_code::SchemaDdlAdmissionCode::GeneratedFieldDefaultChangeRejected
3100 }
3101 Self::GeneratedFieldNullabilityChangeRejected => {
3102 diagnostic_code::SchemaDdlAdmissionCode::GeneratedFieldNullabilityChangeRejected
3103 }
3104 Self::RowLayoutVersionExhausted => {
3105 diagnostic_code::SchemaDdlAdmissionCode::RowLayoutVersionExhausted
3106 }
3107 }
3108 }
3109}
3110
3111#[repr(u8)]
3118#[derive(Clone, Copy, Eq, PartialEq)]
3119pub enum ErrorClass {
3120 Corruption,
3121 IncompatiblePersistedFormat,
3122 NotFound,
3123 Internal,
3124 Conflict,
3125 Unsupported,
3126 InvariantViolation,
3127}
3128
3129impl ErrorClass {
3130 #[must_use]
3132 pub const fn diagnostic_code(self, origin: ErrorOrigin) -> diagnostic_code::DiagnosticCode {
3133 match self {
3134 Self::Corruption if matches!(origin, ErrorOrigin::Store) => {
3135 diagnostic_code::DiagnosticCode::StoreCorruption
3136 }
3137 Self::Corruption => diagnostic_code::DiagnosticCode::RuntimeCorruption,
3138 Self::IncompatiblePersistedFormat => {
3139 diagnostic_code::DiagnosticCode::RuntimeIncompatiblePersistedFormat
3140 }
3141 Self::NotFound if matches!(origin, ErrorOrigin::Store) => {
3142 diagnostic_code::DiagnosticCode::StoreNotFound
3143 }
3144 Self::NotFound => diagnostic_code::DiagnosticCode::RuntimeNotFound,
3145 Self::Internal => diagnostic_code::DiagnosticCode::RuntimeInternal,
3146 Self::Conflict => diagnostic_code::DiagnosticCode::RuntimeConflict,
3147 Self::Unsupported if matches!(origin, ErrorOrigin::Cursor) => {
3148 diagnostic_code::DiagnosticCode::QueryInvalidContinuationCursor
3149 }
3150 Self::Unsupported => diagnostic_code::DiagnosticCode::RuntimeUnsupported,
3151 Self::InvariantViolation if matches!(origin, ErrorOrigin::Store) => {
3152 diagnostic_code::DiagnosticCode::StoreInvariantViolation
3153 }
3154 Self::InvariantViolation => diagnostic_code::DiagnosticCode::RuntimeInvariantViolation,
3155 }
3156 }
3157}
3158
3159impl fmt::Debug for ErrorClass {
3160 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3161 write!(f, "{}", *self as u8)
3162 }
3163}
3164
3165#[repr(u8)]
3172#[derive(Clone, Copy, Eq, PartialEq)]
3173pub enum ErrorOrigin {
3174 Serialize,
3175 Store,
3176 Index,
3177 Identity,
3178 Query,
3179 Planner,
3180 Cursor,
3181 Recovery,
3182 Response,
3183 Executor,
3184 Interface,
3185}
3186
3187impl ErrorOrigin {
3188 #[must_use]
3190 pub const fn diagnostic_origin(self) -> diagnostic_code::ErrorOrigin {
3191 match self {
3192 Self::Serialize => diagnostic_code::ErrorOrigin::Serialize,
3193 Self::Store => diagnostic_code::ErrorOrigin::Store,
3194 Self::Index => diagnostic_code::ErrorOrigin::Index,
3195 Self::Identity => diagnostic_code::ErrorOrigin::Identity,
3196 Self::Query => diagnostic_code::ErrorOrigin::Query,
3197 Self::Planner => diagnostic_code::ErrorOrigin::Planner,
3198 Self::Cursor => diagnostic_code::ErrorOrigin::Cursor,
3199 Self::Recovery => diagnostic_code::ErrorOrigin::Recovery,
3200 Self::Response => diagnostic_code::ErrorOrigin::Response,
3201 Self::Executor => diagnostic_code::ErrorOrigin::Executor,
3202 Self::Interface => diagnostic_code::ErrorOrigin::Interface,
3203 }
3204 }
3205}
3206
3207impl fmt::Debug for ErrorOrigin {
3208 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3209 write!(f, "{}", *self as u8)
3210 }
3211}