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 pub(crate) fn query_unknown_aggregate_target_field() -> Self {
1874 Self {
1875 class: ErrorClass::Unsupported,
1876 origin: ErrorOrigin::Query,
1877 detail: Some(ErrorDetail::Query(
1878 QueryErrorDetail::UnknownAggregateTargetField,
1879 )),
1880 }
1881 }
1882
1883 #[cfg(feature = "sql")]
1886 pub(crate) fn query_sql_surface_mismatch(
1887 mismatch: diagnostic_code::SqlSurfaceMismatchCode,
1888 ) -> Self {
1889 Self {
1890 class: ErrorClass::Unsupported,
1891 origin: ErrorOrigin::Query,
1892 detail: Some(ErrorDetail::Query(QueryErrorDetail::SqlSurfaceMismatch {
1893 mismatch,
1894 })),
1895 }
1896 }
1897
1898 pub(crate) fn query_sql_write_boundary(
1900 boundary: diagnostic_code::SqlWriteBoundaryCode,
1901 ) -> Self {
1902 Self {
1903 class: ErrorClass::Unsupported,
1904 origin: ErrorOrigin::Query,
1905 detail: Some(ErrorDetail::Query(QueryErrorDetail::SqlWriteBoundary {
1906 boundary,
1907 })),
1908 }
1909 }
1910
1911 pub(crate) fn query_sql_write_boundary_with_facts(
1913 boundary: diagnostic_code::SqlWriteBoundaryCode,
1914 facts: Vec<(diagnostic_code::DiagnosticFactTag, u64)>,
1915 ) -> Self {
1916 Self::with_diagnostic_facts(
1917 ErrorClass::Unsupported,
1918 ErrorOrigin::Query,
1919 Some(diagnostic_code::DiagnosticDetail::SqlWriteBoundary { boundary }),
1920 facts,
1921 )
1922 }
1923
1924 pub fn store_not_found(_key: impl Sized) -> Self {
1925 Self {
1926 class: ErrorClass::NotFound,
1927 origin: ErrorOrigin::Store,
1928 detail: Some(ErrorDetail::Store(StoreError::NotFound)),
1929 }
1930 }
1931
1932 pub fn unsupported_entity_path(_path: impl Sized) -> Self {
1934 Self::store_unsupported()
1935 }
1936
1937 #[cold]
1939 #[inline(never)]
1940 pub(crate) fn index_plan_corruption(origin: ErrorOrigin) -> Self {
1941 Self::new(ErrorClass::Corruption, origin)
1942 }
1943
1944 #[cold]
1946 #[inline(never)]
1947 pub(crate) fn index_plan_index_corruption() -> Self {
1948 Self::index_plan_corruption(ErrorOrigin::Index)
1949 }
1950
1951 #[cold]
1953 #[inline(never)]
1954 pub(crate) fn index_plan_store_corruption() -> Self {
1955 Self::index_plan_corruption(ErrorOrigin::Store)
1956 }
1957
1958 #[cold]
1960 #[inline(never)]
1961 pub(crate) fn index_plan_serialize_corruption() -> Self {
1962 Self::index_plan_corruption(ErrorOrigin::Serialize)
1963 }
1964
1965 #[cfg(test)]
1967 pub(crate) fn index_plan_invariant(origin: ErrorOrigin) -> Self {
1968 Self::new(ErrorClass::InvariantViolation, origin)
1969 }
1970
1971 #[cfg(test)]
1973 pub(crate) fn index_plan_store_invariant() -> Self {
1974 Self::index_plan_invariant(ErrorOrigin::Store)
1975 }
1976
1977 pub(crate) fn index_conflict() -> Self {
1983 Self::new(ErrorClass::Conflict, ErrorOrigin::Index)
1984 }
1985}
1986
1987impl From<diagnostic_code::QueryReadAdmissionCode> for InternalError {
1988 fn from(reason: diagnostic_code::QueryReadAdmissionCode) -> Self {
1989 Self {
1990 class: ErrorClass::Unsupported,
1991 origin: ErrorOrigin::Query,
1992 detail: Some(ErrorDetail::Query(QueryErrorDetail::QueryReadAdmission {
1993 reason,
1994 })),
1995 }
1996 }
1997}
1998
1999impl fmt::Debug for InternalError {
2000 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2001 fmt_compact_diagnostic(
2002 f,
2003 self.diagnostic_code(),
2004 self.detail
2005 .as_ref()
2006 .and_then(ErrorDetail::diagnostic_detail),
2007 )
2008 }
2009}
2010
2011impl fmt::Display for InternalError {
2012 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2013 f.write_str(self.message())
2014 }
2015}
2016
2017impl std::error::Error for InternalError {}
2018
2019#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq)]
2028pub enum ConstraintValuePathComponent {
2029 RootField { field_id: u32 },
2031
2032 RecordMember {
2034 composite_type_id: u32,
2035 member_id: u32,
2036 },
2037
2038 TupleElement {
2040 composite_type_id: u32,
2041 ordinal: u32,
2042 },
2043
2044 Newtype { composite_type_id: u32 },
2046
2047 EnumVariant { enum_type_id: u32, variant_id: u32 },
2049
2050 ListElement { index: u32 },
2052
2053 SetElement { index: u32 },
2055
2056 MapEntryKey { index: u32 },
2058
2059 MapEntryValue { index: u32 },
2061}
2062
2063impl fmt::Display for ConstraintValuePathComponent {
2064 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2065 match self {
2066 Self::RootField { field_id } => write!(f, "field#{field_id}"),
2067 Self::RecordMember {
2068 composite_type_id,
2069 member_id,
2070 } => write!(f, "record#{composite_type_id}.member#{member_id}"),
2071 Self::TupleElement {
2072 composite_type_id,
2073 ordinal,
2074 } => write!(f, "tuple#{composite_type_id}[{ordinal}]"),
2075 Self::Newtype { composite_type_id } => write!(f, "newtype#{composite_type_id}"),
2076 Self::EnumVariant {
2077 enum_type_id,
2078 variant_id,
2079 } => write!(f, "enum#{enum_type_id}.variant#{variant_id}"),
2080 Self::ListElement { index } => write!(f, "list[{index}]"),
2081 Self::SetElement { index } => write!(f, "set[{index}]"),
2082 Self::MapEntryKey { index } => write!(f, "map[{index}].key"),
2083 Self::MapEntryValue { index } => write!(f, "map[{index}].value"),
2084 }
2085 }
2086}
2087
2088#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
2095pub struct ConstraintValuePath {
2096 components: Vec<ConstraintValuePathComponent>,
2097}
2098
2099impl ConstraintValuePath {
2100 #[must_use]
2102 pub(crate) const fn new(components: Vec<ConstraintValuePathComponent>) -> Self {
2103 Self { components }
2104 }
2105
2106 #[must_use]
2108 pub const fn components(&self) -> &[ConstraintValuePathComponent] {
2109 self.components.as_slice()
2110 }
2111}
2112
2113impl fmt::Display for ConstraintValuePath {
2114 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2115 for (ordinal, component) in self.components.iter().enumerate() {
2116 if ordinal != 0 {
2117 f.write_str("/")?;
2118 }
2119 component.fmt(f)?;
2120 }
2121 Ok(())
2122 }
2123}
2124
2125#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
2134pub struct ConstraintValidationFindingOutput {
2135 accepted_schema_fingerprint: [u8; 16],
2136 entity_tag: u64,
2137 constraint_id: u32,
2138 primary_key: Vec<u8>,
2139 field_ids: Vec<u32>,
2140 value_path: Option<ConstraintValuePath>,
2141 error_code: u16,
2142}
2143
2144impl ConstraintValidationFindingOutput {
2145 #[must_use]
2147 pub(crate) const fn new(
2148 accepted_schema_fingerprint: [u8; 16],
2149 entity_tag: u64,
2150 constraint_id: u32,
2151 primary_key: Vec<u8>,
2152 field_ids: Vec<u32>,
2153 value_path: Option<ConstraintValuePath>,
2154 error_code: u16,
2155 ) -> Self {
2156 Self {
2157 accepted_schema_fingerprint,
2158 entity_tag,
2159 constraint_id,
2160 primary_key,
2161 field_ids,
2162 value_path,
2163 error_code,
2164 }
2165 }
2166
2167 #[must_use]
2169 pub const fn accepted_schema_fingerprint(&self) -> [u8; 16] {
2170 self.accepted_schema_fingerprint
2171 }
2172
2173 #[must_use]
2175 pub const fn entity_tag(&self) -> u64 {
2176 self.entity_tag
2177 }
2178
2179 #[must_use]
2181 pub const fn constraint_id(&self) -> u32 {
2182 self.constraint_id
2183 }
2184
2185 #[must_use]
2187 pub const fn primary_key(&self) -> &[u8] {
2188 self.primary_key.as_slice()
2189 }
2190
2191 #[must_use]
2193 pub const fn field_ids(&self) -> &[u32] {
2194 self.field_ids.as_slice()
2195 }
2196
2197 #[must_use]
2199 pub const fn value_path(&self) -> Option<&ConstraintValuePath> {
2200 self.value_path.as_ref()
2201 }
2202
2203 #[must_use]
2205 pub const fn error_code(&self) -> diagnostic_code::ErrorCode {
2206 diagnostic_code::ErrorCode::from_raw(self.error_code)
2207 }
2208
2209 #[must_use]
2211 pub const fn error_class(&self) -> diagnostic_code::ErrorClass {
2212 self.error_code().class()
2213 }
2214}
2215
2216#[derive(Clone)]
2218pub(crate) struct AcceptedConstraintFactContext {
2219 fingerprint_method: u8,
2220 accepted_schema_fingerprint: [u8; 16],
2221 entity_tag: u64,
2222 constraint_id: u32,
2223 constraint_kind: diagnostic_code::DiagnosticConstraintKind,
2224 mutation: Option<MutationDiagnosticContext>,
2225 value_path: Option<ConstraintValuePath>,
2226}
2227
2228impl AcceptedConstraintFactContext {
2229 #[must_use]
2230 pub(crate) fn write_admission(
2231 fingerprint_method: u8,
2232 accepted_schema_fingerprint: [u8; 16],
2233 entity_tag: u64,
2234 constraint_id: u32,
2235 constraint_kind: diagnostic_code::DiagnosticConstraintKind,
2236 mutation: Option<MutationDiagnosticContext>,
2237 value_path: Option<ConstraintValuePath>,
2238 ) -> Self {
2239 debug_assert!(mutation.is_none_or(|context| context.entity_tag() == entity_tag));
2240 Self {
2241 fingerprint_method,
2242 accepted_schema_fingerprint,
2243 entity_tag,
2244 constraint_id,
2245 constraint_kind,
2246 mutation,
2247 value_path,
2248 }
2249 }
2250
2251 fn facts(self) -> Vec<(diagnostic_code::DiagnosticFactTag, u64)> {
2252 let high = u64::from_be_bytes([
2253 self.accepted_schema_fingerprint[0],
2254 self.accepted_schema_fingerprint[1],
2255 self.accepted_schema_fingerprint[2],
2256 self.accepted_schema_fingerprint[3],
2257 self.accepted_schema_fingerprint[4],
2258 self.accepted_schema_fingerprint[5],
2259 self.accepted_schema_fingerprint[6],
2260 self.accepted_schema_fingerprint[7],
2261 ]);
2262 let low = u64::from_be_bytes([
2263 self.accepted_schema_fingerprint[8],
2264 self.accepted_schema_fingerprint[9],
2265 self.accepted_schema_fingerprint[10],
2266 self.accepted_schema_fingerprint[11],
2267 self.accepted_schema_fingerprint[12],
2268 self.accepted_schema_fingerprint[13],
2269 self.accepted_schema_fingerprint[14],
2270 self.accepted_schema_fingerprint[15],
2271 ]);
2272 let path_len = self
2273 .value_path
2274 .as_ref()
2275 .map_or(0, |path| path.components().len());
2276 let mutation_fact_count = self.mutation.map_or(0, |mutation| {
2277 1 + usize::from(mutation.batch_position.is_some())
2278 });
2279 let mut facts = Vec::with_capacity(7 + mutation_fact_count + path_len);
2280 facts.push((
2281 diagnostic_code::DiagnosticFactTag::AcceptedSchemaFingerprintMethod,
2282 u64::from(self.fingerprint_method),
2283 ));
2284 facts.push((
2285 diagnostic_code::DiagnosticFactTag::AcceptedSchemaFingerprintHigh,
2286 high,
2287 ));
2288 facts.push((
2289 diagnostic_code::DiagnosticFactTag::AcceptedSchemaFingerprintLow,
2290 low,
2291 ));
2292 facts.push((
2293 diagnostic_code::DiagnosticFactTag::EntityTag,
2294 self.entity_tag,
2295 ));
2296 facts.push((
2297 diagnostic_code::DiagnosticFactTag::ConstraintId,
2298 u64::from(self.constraint_id),
2299 ));
2300 facts.push((
2301 diagnostic_code::DiagnosticFactTag::ConstraintKind,
2302 self.constraint_kind.raw(),
2303 ));
2304 facts.push((
2305 diagnostic_code::DiagnosticFactTag::ConstraintContext,
2306 diagnostic_code::DiagnosticConstraintContext::WriteAdmission.raw(),
2307 ));
2308 if let Some(mutation) = self.mutation {
2309 mutation.append_operation_facts(&mut facts);
2310 }
2311 if let Some(path) = self.value_path {
2312 for component in path.components {
2313 facts.push(constraint_value_path_fact(component));
2314 }
2315 }
2316 debug_assert!(facts.len() <= diagnostic_code::MAX_PUBLIC_DIAGNOSTIC_FACTS);
2317 facts
2318 }
2319}
2320
2321fn constraint_value_path_fact(
2322 component: ConstraintValuePathComponent,
2323) -> (diagnostic_code::DiagnosticFactTag, u64) {
2324 use diagnostic_code::DiagnosticFactTag;
2325 match component {
2326 ConstraintValuePathComponent::RootField { field_id } => {
2327 (DiagnosticFactTag::RootField, u64::from(field_id))
2328 }
2329 ConstraintValuePathComponent::RecordMember {
2330 composite_type_id,
2331 member_id,
2332 } => (
2333 DiagnosticFactTag::RecordMember,
2334 diagnostic_code::pack_u32_pair(composite_type_id, member_id),
2335 ),
2336 ConstraintValuePathComponent::TupleElement {
2337 composite_type_id,
2338 ordinal,
2339 } => (
2340 DiagnosticFactTag::TupleElement,
2341 diagnostic_code::pack_u32_pair(composite_type_id, ordinal),
2342 ),
2343 ConstraintValuePathComponent::Newtype { composite_type_id } => {
2344 (DiagnosticFactTag::Newtype, u64::from(composite_type_id))
2345 }
2346 ConstraintValuePathComponent::EnumVariant {
2347 enum_type_id,
2348 variant_id,
2349 } => (
2350 DiagnosticFactTag::EnumVariant,
2351 diagnostic_code::pack_u32_pair(enum_type_id, variant_id),
2352 ),
2353 ConstraintValuePathComponent::ListElement { index } => {
2354 (DiagnosticFactTag::ListElement, u64::from(index))
2355 }
2356 ConstraintValuePathComponent::SetElement { index } => {
2357 (DiagnosticFactTag::SetElement, u64::from(index))
2358 }
2359 ConstraintValuePathComponent::MapEntryKey { index } => {
2360 (DiagnosticFactTag::MapEntryKey, u64::from(index))
2361 }
2362 ConstraintValuePathComponent::MapEntryValue { index } => {
2363 (DiagnosticFactTag::MapEntryValue, u64::from(index))
2364 }
2365 }
2366}
2367
2368pub enum ErrorDetail {
2376 DiagnosticFacts(Box<DiagnosticFactDetail>),
2378 Executor(ExecutorErrorDetail),
2380 Store(StoreError),
2381 Query(QueryErrorDetail),
2382 Recovery(RecoveryErrorDetail),
2383 }
2386
2387pub enum ExecutorErrorDetail {
2389 MutationRequiredFieldMissing,
2391 MutationManagedTimestampRegression,
2393 MutationDatabaseOwnedFieldExplicit,
2395 MutationBatchEmpty,
2397 MutationBatchTooManyItems,
2399 MutationBatchStagedBytesExceeded,
2401 MutationBatchResultBytesExceeded,
2403 MutationBatchEntityMismatch,
2405 MutationBatchDuplicateKey,
2407 AcceptedRowConstraintProgramCorrupt,
2409}
2410
2411pub enum RecoveryErrorDetail {
2418 UnsupportedFormatVersion { found: Option<u16>, required: u16 },
2419
2420 MalformedFormatMarker { reason: RecoveryFormatMarkerError },
2421}
2422
2423#[derive(Clone, Copy, Eq, PartialEq)]
2425pub enum RecoveryFormatMarkerError {
2426 Magic,
2427 Checksum,
2428 State,
2429}
2430
2431impl RecoveryFormatMarkerError {
2432 const fn diagnostic_decode_reason(self) -> diagnostic_code::DiagnosticDecodeReason {
2433 match self {
2434 Self::Magic => diagnostic_code::DiagnosticDecodeReason::RecoveryMarkerMagic,
2435 Self::Checksum => diagnostic_code::DiagnosticDecodeReason::RecoveryMarkerChecksum,
2436 Self::State => diagnostic_code::DiagnosticDecodeReason::RecoveryMarkerState,
2437 }
2438 }
2439}
2440
2441pub enum StoreError {
2449 NotFound,
2450
2451 Corrupt,
2452
2453 InvariantViolation,
2454
2455 SchemaDdlPublicationRaceLost,
2456
2457 SchemaDdlRewriteRequiresMigration,
2458
2459 SchemaMigration {
2460 reason: diagnostic_code::SchemaMigrationCode,
2461 },
2462
2463 SchemaRowLayoutVersionExhausted,
2464
2465 JournalMutationRevisionExhausted,
2466
2467 SchemaTransitionBudgetExceeded {
2468 resource: SchemaTransitionBudgetResource,
2469 },
2470
2471 SchemaGeneratedFieldAfterDdlField,
2473
2474 SchemaGeneratedConstraintActivationStale,
2476}
2477
2478pub enum QueryErrorDetail {
2485 NumericOverflow,
2486
2487 NumericNotRepresentable,
2488
2489 UnsupportedSqlFeature {
2490 feature: diagnostic_code::SqlFeatureCode,
2491 },
2492
2493 SqlLowering {
2494 reason: diagnostic_code::SqlLoweringCode,
2495 },
2496
2497 UnsupportedProjection {
2498 reason: diagnostic_code::QueryProjectionCode,
2499 },
2500
2501 UnknownAggregateTargetField,
2502
2503 ResultShapeMismatch {
2504 reason: diagnostic_code::QueryResultShapeCode,
2505 },
2506
2507 QueryReadAdmission {
2508 reason: diagnostic_code::QueryReadAdmissionCode,
2509 },
2510
2511 SqlSurfaceMismatch {
2512 mismatch: diagnostic_code::SqlSurfaceMismatchCode,
2513 },
2514
2515 SqlWriteBoundary {
2516 boundary: diagnostic_code::SqlWriteBoundaryCode,
2517 },
2518
2519 SchemaDdlAdmission {
2520 error: SchemaDdlAdmissionError,
2521 },
2522
2523 StaleSchemaRevision,
2524}
2525
2526impl fmt::Display for QueryErrorDetail {
2527 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2528 f.write_str(COMPACT_QUERY_DIAGNOSTIC_MESSAGE)
2529 }
2530}
2531
2532impl std::error::Error for QueryErrorDetail {}
2533
2534#[derive(Clone, Copy, Debug, Eq, PartialEq)]
2542pub enum SchemaTransitionBudgetResource {
2543 DeletionKeys,
2545 ProjectionEntries,
2547 ProjectionWorkUnits,
2549 SourceRows,
2551 SourceRowBytes,
2553 StagedRawBytes,
2555}
2556
2557#[derive(Clone, Copy, Eq, PartialEq)]
2566pub enum SchemaDdlAdmissionError {
2567 MissingExpectedSchemaVersion,
2568
2569 MissingNextSchemaVersion,
2570
2571 StaleExpectedSchemaVersion,
2572
2573 InvalidExpectedSchemaVersion,
2574
2575 InvalidNextSchemaVersion,
2576
2577 AcceptedSchemaChangeWithoutVersionBump,
2578
2579 EmptyVersionBump,
2580
2581 VersionGap,
2582
2583 VersionRollback,
2584
2585 FingerprintMethodMismatch,
2586
2587 UnsupportedTransitionClass,
2588
2589 PhysicalRunnerMissing,
2590
2591 ValidationFailed,
2592
2593 PublicationRaceLost,
2594
2595 InvalidAddColumnDefault,
2596
2597 InvalidAlterColumnDefault,
2598
2599 RowLayoutVersionExhausted,
2600
2601 GeneratedIndexDropRejected,
2602
2603 SchemaRewriteRequiresMigration,
2604
2605 SchemaTransitionBudgetExceeded {
2606 resource: SchemaTransitionBudgetResource,
2607 },
2608
2609 GeneratedFieldDefaultChangeRejected,
2610
2611 GeneratedFieldNullabilityChangeRejected,
2612}
2613
2614impl fmt::Display for SchemaDdlAdmissionError {
2615 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2616 f.write_str(COMPACT_QUERY_DIAGNOSTIC_MESSAGE)
2617 }
2618}
2619
2620impl std::error::Error for SchemaDdlAdmissionError {}
2621
2622impl fmt::Debug for ErrorDetail {
2623 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2624 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2625 }
2626}
2627
2628impl fmt::Debug for ExecutorErrorDetail {
2629 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2630 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2631 }
2632}
2633
2634impl fmt::Debug for StoreError {
2635 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2636 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2637 }
2638}
2639
2640impl fmt::Debug for QueryErrorDetail {
2641 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2642 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2643 }
2644}
2645
2646impl fmt::Debug for RecoveryErrorDetail {
2647 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2648 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2649 }
2650}
2651
2652impl fmt::Debug for RecoveryFormatMarkerError {
2653 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2654 fmt_compact_diagnostic(
2655 f,
2656 diagnostic_code::DiagnosticCode::RuntimeCorruption,
2657 Some(diagnostic_code::DiagnosticDetail::RuntimeKind {
2658 kind: diagnostic_code::RuntimeErrorKind::Corruption,
2659 }),
2660 )
2661 }
2662}
2663
2664impl fmt::Debug for SchemaDdlAdmissionError {
2665 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2666 fmt_compact_diagnostic(
2667 f,
2668 diagnostic_code::DiagnosticCode::SchemaDdlAdmission,
2669 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2670 reason: self.diagnostic_code(),
2671 }),
2672 )
2673 }
2674}
2675
2676fn fmt_compact_diagnostic(
2677 f: &mut fmt::Formatter<'_>,
2678 code: diagnostic_code::DiagnosticCode,
2679 detail: Option<diagnostic_code::DiagnosticDetail>,
2680) -> fmt::Result {
2681 write!(
2682 f,
2683 "{}",
2684 diagnostic_code::ErrorCode::from_parts(code, detail).raw()
2685 )
2686}
2687
2688impl ErrorDetail {
2689 #[must_use]
2691 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2692 match self {
2693 Self::DiagnosticFacts(detail) => detail.diagnostic.code(),
2694 Self::Executor(error) => error.diagnostic_code(),
2695 Self::Store(error) => error.diagnostic_code(),
2696 Self::Query(error) => error.diagnostic_code(),
2697 Self::Recovery(error) => error.diagnostic_code(),
2698 }
2699 }
2700
2701 #[must_use]
2703 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2704 match self {
2705 Self::DiagnosticFacts(detail) => detail.diagnostic.detail().copied(),
2706 Self::Executor(error) => error.diagnostic_detail(),
2707 Self::Store(error) => error.diagnostic_detail(),
2708 Self::Query(error) => error.diagnostic_detail(),
2709 Self::Recovery(error) => error.diagnostic_detail(),
2710 }
2711 }
2712
2713 #[must_use]
2715 #[cold]
2716 #[inline(never)]
2717 pub fn diagnostic_facts(&self) -> Vec<(diagnostic_code::DiagnosticFactTag, u64)> {
2718 match self {
2719 Self::DiagnosticFacts(detail) => detail.facts.clone(),
2720 Self::Executor(error) => error.diagnostic_facts(),
2721 Self::Query(error) => error.diagnostic_facts(),
2722 Self::Recovery(error) => error.diagnostic_facts(),
2723 Self::Store(_) => Vec::new(),
2724 }
2725 }
2726}
2727
2728impl ExecutorErrorDetail {
2729 #[must_use]
2731 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2732 match self {
2733 Self::MutationRequiredFieldMissing
2734 | Self::MutationDatabaseOwnedFieldExplicit
2735 | Self::MutationBatchEmpty
2736 | Self::MutationBatchTooManyItems
2737 | Self::MutationBatchStagedBytesExceeded
2738 | Self::MutationBatchResultBytesExceeded => {
2739 diagnostic_code::DiagnosticCode::RuntimeUnsupported
2740 }
2741 Self::MutationBatchEntityMismatch | Self::MutationBatchDuplicateKey => {
2742 diagnostic_code::DiagnosticCode::RuntimeConflict
2743 }
2744 Self::MutationManagedTimestampRegression => {
2745 diagnostic_code::DiagnosticCode::RuntimeInvariantViolation
2746 }
2747 Self::AcceptedRowConstraintProgramCorrupt => {
2748 diagnostic_code::DiagnosticCode::RuntimeCorruption
2749 }
2750 }
2751 }
2752
2753 #[must_use]
2755 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2756 match self {
2757 Self::MutationRequiredFieldMissing => {
2758 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2759 boundary: diagnostic_code::RuntimeBoundaryCode::MutationRequiredFieldMissing,
2760 })
2761 }
2762 Self::MutationDatabaseOwnedFieldExplicit => {
2763 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2764 boundary:
2765 diagnostic_code::RuntimeBoundaryCode::MutationDatabaseOwnedFieldExplicit,
2766 })
2767 }
2768 Self::MutationBatchEmpty => Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2769 boundary: diagnostic_code::RuntimeBoundaryCode::MutationBatchEmpty,
2770 }),
2771 Self::MutationBatchTooManyItems => {
2772 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2773 boundary: diagnostic_code::RuntimeBoundaryCode::MutationBatchTooManyItems,
2774 })
2775 }
2776 Self::MutationBatchStagedBytesExceeded => {
2777 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2778 boundary:
2779 diagnostic_code::RuntimeBoundaryCode::MutationBatchStagedBytesExceeded,
2780 })
2781 }
2782 Self::MutationBatchResultBytesExceeded => {
2783 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2784 boundary:
2785 diagnostic_code::RuntimeBoundaryCode::MutationBatchResultBytesExceeded,
2786 })
2787 }
2788 Self::MutationBatchEntityMismatch => {
2789 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2790 boundary: diagnostic_code::RuntimeBoundaryCode::MutationBatchEntityMismatch,
2791 })
2792 }
2793 Self::MutationBatchDuplicateKey => {
2794 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2795 boundary: diagnostic_code::RuntimeBoundaryCode::MutationBatchDuplicateKey,
2796 })
2797 }
2798 Self::MutationManagedTimestampRegression => {
2799 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2800 boundary:
2801 diagnostic_code::RuntimeBoundaryCode::MutationManagedTimestampRegression,
2802 })
2803 }
2804 Self::AcceptedRowConstraintProgramCorrupt => {
2805 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2806 boundary:
2807 diagnostic_code::RuntimeBoundaryCode::AcceptedRowConstraintProgramCorrupt,
2808 })
2809 }
2810 }
2811 }
2812
2813 #[must_use]
2815 #[cold]
2816 #[inline(never)]
2817 pub const fn diagnostic_facts(&self) -> Vec<(diagnostic_code::DiagnosticFactTag, u64)> {
2818 Vec::new()
2819 }
2820}
2821
2822impl RecoveryErrorDetail {
2823 #[must_use]
2825 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2826 match self {
2827 Self::UnsupportedFormatVersion { .. } => {
2828 diagnostic_code::DiagnosticCode::RuntimeIncompatiblePersistedFormat
2829 }
2830 Self::MalformedFormatMarker { .. } => {
2831 diagnostic_code::DiagnosticCode::RuntimeCorruption
2832 }
2833 }
2834 }
2835
2836 #[must_use]
2838 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2839 let kind = match self {
2840 Self::UnsupportedFormatVersion { .. } => {
2841 diagnostic_code::RuntimeErrorKind::IncompatiblePersistedFormat
2842 }
2843 Self::MalformedFormatMarker { .. } => diagnostic_code::RuntimeErrorKind::Corruption,
2844 };
2845
2846 Some(diagnostic_code::DiagnosticDetail::RuntimeKind { kind })
2847 }
2848
2849 #[must_use]
2851 pub fn diagnostic_facts(&self) -> Vec<(diagnostic_code::DiagnosticFactTag, u64)> {
2852 match self {
2853 Self::UnsupportedFormatVersion { found, required } => {
2854 let mut facts = Vec::with_capacity(usize::from(found.is_some()) + 1);
2855 facts.push((
2856 diagnostic_code::DiagnosticFactTag::ExpectedVersion,
2857 u64::from(*required),
2858 ));
2859 if let Some(found) = found {
2860 facts.push((
2861 diagnostic_code::DiagnosticFactTag::ActualVersion,
2862 u64::from(*found),
2863 ));
2864 }
2865 facts
2866 }
2867 Self::MalformedFormatMarker { reason } => vec![(
2868 diagnostic_code::DiagnosticFactTag::DecodeReason,
2869 reason.diagnostic_decode_reason().raw(),
2870 )],
2871 }
2872 }
2873}
2874
2875impl StoreError {
2876 #[must_use]
2878 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2879 match self {
2880 Self::NotFound => diagnostic_code::DiagnosticCode::StoreNotFound,
2881 Self::Corrupt => diagnostic_code::DiagnosticCode::StoreCorruption,
2882 Self::InvariantViolation => diagnostic_code::DiagnosticCode::StoreInvariantViolation,
2883 Self::SchemaDdlPublicationRaceLost
2884 | Self::SchemaDdlRewriteRequiresMigration
2885 | Self::SchemaRowLayoutVersionExhausted
2886 | Self::SchemaTransitionBudgetExceeded { .. } => {
2887 diagnostic_code::DiagnosticCode::SchemaDdlAdmission
2888 }
2889 Self::JournalMutationRevisionExhausted | Self::SchemaGeneratedFieldAfterDdlField => {
2890 diagnostic_code::DiagnosticCode::RuntimeUnsupported
2891 }
2892 Self::SchemaGeneratedConstraintActivationStale => {
2893 diagnostic_code::DiagnosticCode::RuntimeConflict
2894 }
2895 Self::SchemaMigration { reason } => reason.diagnostic_code(),
2896 }
2897 }
2898
2899 #[must_use]
2901 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2902 match self {
2903 Self::SchemaDdlPublicationRaceLost => {
2904 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2905 reason: diagnostic_code::SchemaDdlAdmissionCode::PublicationRaceLost,
2906 })
2907 }
2908 Self::SchemaDdlRewriteRequiresMigration => {
2909 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2910 reason: diagnostic_code::SchemaDdlAdmissionCode::SchemaRewriteRequiresMigration,
2911 })
2912 }
2913 Self::SchemaMigration { reason } => {
2914 Some(diagnostic_code::DiagnosticDetail::SchemaMigration { reason: *reason })
2915 }
2916 Self::SchemaRowLayoutVersionExhausted => {
2917 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2918 reason: diagnostic_code::SchemaDdlAdmissionCode::RowLayoutVersionExhausted,
2919 })
2920 }
2921 Self::JournalMutationRevisionExhausted => {
2922 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2923 boundary:
2924 diagnostic_code::RuntimeBoundaryCode::JournalMutationRevisionExhausted,
2925 })
2926 }
2927 Self::SchemaTransitionBudgetExceeded { .. } => {
2928 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2929 reason: diagnostic_code::SchemaDdlAdmissionCode::SchemaTransitionBudgetExceeded,
2930 })
2931 }
2932 Self::SchemaGeneratedFieldAfterDdlField => {
2933 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2934 boundary: diagnostic_code::RuntimeBoundaryCode::GeneratedFieldAfterDdlField,
2935 })
2936 }
2937 Self::SchemaGeneratedConstraintActivationStale => {
2938 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2939 boundary:
2940 diagnostic_code::RuntimeBoundaryCode::GeneratedConstraintActivationStale,
2941 })
2942 }
2943 Self::NotFound | Self::Corrupt | Self::InvariantViolation => None,
2944 }
2945 }
2946}
2947
2948impl QueryErrorDetail {
2949 #[must_use]
2951 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2952 match self {
2953 Self::NumericOverflow => diagnostic_code::DiagnosticCode::QueryNumericOverflow,
2954 Self::NumericNotRepresentable => {
2955 diagnostic_code::DiagnosticCode::QueryNumericNotRepresentable
2956 }
2957 Self::UnsupportedSqlFeature { .. } => {
2958 diagnostic_code::DiagnosticCode::QueryUnsupportedSqlFeature
2959 }
2960 Self::SqlLowering { .. } => diagnostic_code::DiagnosticCode::QueryUnsupportedSqlFeature,
2961 Self::UnsupportedProjection { .. } => {
2962 diagnostic_code::DiagnosticCode::QueryUnsupportedProjection
2963 }
2964 Self::UnknownAggregateTargetField => {
2965 diagnostic_code::DiagnosticCode::QueryUnknownAggregateTargetField
2966 }
2967 Self::ResultShapeMismatch { .. } => {
2968 diagnostic_code::DiagnosticCode::QueryResultShapeMismatch
2969 }
2970 Self::QueryReadAdmission { .. } => diagnostic_code::DiagnosticCode::QueryReadAdmission,
2971 Self::SqlSurfaceMismatch { .. } => {
2972 diagnostic_code::DiagnosticCode::QuerySqlSurfaceMismatch
2973 }
2974 Self::SqlWriteBoundary { .. } => diagnostic_code::DiagnosticCode::QuerySqlWriteBoundary,
2975 Self::SchemaDdlAdmission { .. } => diagnostic_code::DiagnosticCode::SchemaDdlAdmission,
2976 Self::StaleSchemaRevision => diagnostic_code::DiagnosticCode::RuntimeConflict,
2977 }
2978 }
2979
2980 #[must_use]
2982 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2983 match self {
2984 Self::UnsupportedSqlFeature { feature } => {
2985 Some(diagnostic_code::DiagnosticDetail::UnsupportedSqlFeature { feature: *feature })
2986 }
2987 Self::SqlLowering { reason } => {
2988 Some(diagnostic_code::DiagnosticDetail::SqlLowering { reason: *reason })
2989 }
2990 Self::UnsupportedProjection { reason } => {
2991 Some(diagnostic_code::DiagnosticDetail::QueryProjection { reason: *reason })
2992 }
2993 Self::ResultShapeMismatch { reason } => {
2994 Some(diagnostic_code::DiagnosticDetail::QueryResultShape { reason: *reason })
2995 }
2996 Self::QueryReadAdmission { reason } => {
2997 Some(diagnostic_code::DiagnosticDetail::QueryReadAdmission { reason: *reason })
2998 }
2999 Self::SqlSurfaceMismatch { mismatch } => {
3000 Some(diagnostic_code::DiagnosticDetail::SqlSurfaceMismatch {
3001 mismatch: *mismatch,
3002 })
3003 }
3004 Self::SqlWriteBoundary { boundary } => {
3005 Some(diagnostic_code::DiagnosticDetail::SqlWriteBoundary {
3006 boundary: *boundary,
3007 })
3008 }
3009 Self::SchemaDdlAdmission { error } => {
3010 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
3011 reason: error.diagnostic_code(),
3012 })
3013 }
3014 Self::NumericOverflow
3015 | Self::NumericNotRepresentable
3016 | Self::UnknownAggregateTargetField
3017 | Self::StaleSchemaRevision => None,
3018 }
3019 }
3020
3021 #[must_use]
3023 #[cold]
3024 #[inline(never)]
3025 pub const fn diagnostic_facts(&self) -> Vec<(diagnostic_code::DiagnosticFactTag, u64)> {
3026 Vec::new()
3027 }
3028}
3029
3030impl SchemaDdlAdmissionError {
3031 #[must_use]
3033 pub const fn diagnostic_code(&self) -> diagnostic_code::SchemaDdlAdmissionCode {
3034 match self {
3035 Self::MissingExpectedSchemaVersion => {
3036 diagnostic_code::SchemaDdlAdmissionCode::MissingExpectedSchemaVersion
3037 }
3038 Self::MissingNextSchemaVersion => {
3039 diagnostic_code::SchemaDdlAdmissionCode::MissingNextSchemaVersion
3040 }
3041 Self::StaleExpectedSchemaVersion => {
3042 diagnostic_code::SchemaDdlAdmissionCode::StaleExpectedSchemaVersion
3043 }
3044 Self::InvalidExpectedSchemaVersion => {
3045 diagnostic_code::SchemaDdlAdmissionCode::InvalidExpectedSchemaVersion
3046 }
3047 Self::InvalidNextSchemaVersion => {
3048 diagnostic_code::SchemaDdlAdmissionCode::InvalidNextSchemaVersion
3049 }
3050 Self::AcceptedSchemaChangeWithoutVersionBump => {
3051 diagnostic_code::SchemaDdlAdmissionCode::AcceptedSchemaChangeWithoutVersionBump
3052 }
3053 Self::EmptyVersionBump => diagnostic_code::SchemaDdlAdmissionCode::EmptyVersionBump,
3054 Self::VersionGap => diagnostic_code::SchemaDdlAdmissionCode::VersionGap,
3055 Self::VersionRollback => diagnostic_code::SchemaDdlAdmissionCode::VersionRollback,
3056 Self::FingerprintMethodMismatch => {
3057 diagnostic_code::SchemaDdlAdmissionCode::FingerprintMethodMismatch
3058 }
3059 Self::UnsupportedTransitionClass => {
3060 diagnostic_code::SchemaDdlAdmissionCode::UnsupportedTransitionClass
3061 }
3062 Self::PhysicalRunnerMissing => {
3063 diagnostic_code::SchemaDdlAdmissionCode::PhysicalRunnerMissing
3064 }
3065 Self::ValidationFailed => diagnostic_code::SchemaDdlAdmissionCode::ValidationFailed,
3066 Self::PublicationRaceLost => {
3067 diagnostic_code::SchemaDdlAdmissionCode::PublicationRaceLost
3068 }
3069 Self::InvalidAddColumnDefault => {
3070 diagnostic_code::SchemaDdlAdmissionCode::InvalidAddColumnDefault
3071 }
3072 Self::InvalidAlterColumnDefault => {
3073 diagnostic_code::SchemaDdlAdmissionCode::InvalidAlterColumnDefault
3074 }
3075 Self::GeneratedIndexDropRejected => {
3076 diagnostic_code::SchemaDdlAdmissionCode::GeneratedIndexDropRejected
3077 }
3078 Self::SchemaRewriteRequiresMigration => {
3079 diagnostic_code::SchemaDdlAdmissionCode::SchemaRewriteRequiresMigration
3080 }
3081 Self::SchemaTransitionBudgetExceeded { .. } => {
3082 diagnostic_code::SchemaDdlAdmissionCode::SchemaTransitionBudgetExceeded
3083 }
3084 Self::GeneratedFieldDefaultChangeRejected => {
3085 diagnostic_code::SchemaDdlAdmissionCode::GeneratedFieldDefaultChangeRejected
3086 }
3087 Self::GeneratedFieldNullabilityChangeRejected => {
3088 diagnostic_code::SchemaDdlAdmissionCode::GeneratedFieldNullabilityChangeRejected
3089 }
3090 Self::RowLayoutVersionExhausted => {
3091 diagnostic_code::SchemaDdlAdmissionCode::RowLayoutVersionExhausted
3092 }
3093 }
3094 }
3095}
3096
3097#[repr(u8)]
3104#[derive(Clone, Copy, Eq, PartialEq)]
3105pub enum ErrorClass {
3106 Corruption,
3107 IncompatiblePersistedFormat,
3108 NotFound,
3109 Internal,
3110 Conflict,
3111 Unsupported,
3112 InvariantViolation,
3113}
3114
3115impl ErrorClass {
3116 #[must_use]
3118 pub const fn diagnostic_code(self, origin: ErrorOrigin) -> diagnostic_code::DiagnosticCode {
3119 match self {
3120 Self::Corruption if matches!(origin, ErrorOrigin::Store) => {
3121 diagnostic_code::DiagnosticCode::StoreCorruption
3122 }
3123 Self::Corruption => diagnostic_code::DiagnosticCode::RuntimeCorruption,
3124 Self::IncompatiblePersistedFormat => {
3125 diagnostic_code::DiagnosticCode::RuntimeIncompatiblePersistedFormat
3126 }
3127 Self::NotFound if matches!(origin, ErrorOrigin::Store) => {
3128 diagnostic_code::DiagnosticCode::StoreNotFound
3129 }
3130 Self::NotFound => diagnostic_code::DiagnosticCode::RuntimeNotFound,
3131 Self::Internal => diagnostic_code::DiagnosticCode::RuntimeInternal,
3132 Self::Conflict => diagnostic_code::DiagnosticCode::RuntimeConflict,
3133 Self::Unsupported if matches!(origin, ErrorOrigin::Cursor) => {
3134 diagnostic_code::DiagnosticCode::QueryInvalidContinuationCursor
3135 }
3136 Self::Unsupported => diagnostic_code::DiagnosticCode::RuntimeUnsupported,
3137 Self::InvariantViolation if matches!(origin, ErrorOrigin::Store) => {
3138 diagnostic_code::DiagnosticCode::StoreInvariantViolation
3139 }
3140 Self::InvariantViolation => diagnostic_code::DiagnosticCode::RuntimeInvariantViolation,
3141 }
3142 }
3143}
3144
3145impl fmt::Debug for ErrorClass {
3146 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3147 write!(f, "{}", *self as u8)
3148 }
3149}
3150
3151#[repr(u8)]
3158#[derive(Clone, Copy, Eq, PartialEq)]
3159pub enum ErrorOrigin {
3160 Serialize,
3161 Store,
3162 Index,
3163 Identity,
3164 Query,
3165 Planner,
3166 Cursor,
3167 Recovery,
3168 Response,
3169 Executor,
3170 Interface,
3171}
3172
3173impl ErrorOrigin {
3174 #[must_use]
3176 pub const fn diagnostic_origin(self) -> diagnostic_code::ErrorOrigin {
3177 match self {
3178 Self::Serialize => diagnostic_code::ErrorOrigin::Serialize,
3179 Self::Store => diagnostic_code::ErrorOrigin::Store,
3180 Self::Index => diagnostic_code::ErrorOrigin::Index,
3181 Self::Identity => diagnostic_code::ErrorOrigin::Identity,
3182 Self::Query => diagnostic_code::ErrorOrigin::Query,
3183 Self::Planner => diagnostic_code::ErrorOrigin::Planner,
3184 Self::Cursor => diagnostic_code::ErrorOrigin::Cursor,
3185 Self::Recovery => diagnostic_code::ErrorOrigin::Recovery,
3186 Self::Response => diagnostic_code::ErrorOrigin::Response,
3187 Self::Executor => diagnostic_code::ErrorOrigin::Executor,
3188 Self::Interface => diagnostic_code::ErrorOrigin::Interface,
3189 }
3190 }
3191}
3192
3193impl fmt::Debug for ErrorOrigin {
3194 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3195 write!(f, "{}", *self as u8)
3196 }
3197}