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
39pub struct InternalError {
140 pub(crate) class: ErrorClass,
141 pub(crate) origin: ErrorOrigin,
142
143 pub(crate) detail: Option<ErrorDetail>,
146}
147
148#[expect(
149 clippy::missing_const_for_fn,
150 reason = "internal error constructors stay non-const so compact diagnostic construction does not force const churn across subsystem helper seams"
151)]
152impl InternalError {
153 #[must_use]
157 #[cold]
158 #[inline(never)]
159 pub fn new(class: ErrorClass, origin: ErrorOrigin) -> Self {
160 let detail = match (class, origin) {
161 (ErrorClass::Corruption, ErrorOrigin::Store) => {
162 Some(ErrorDetail::Store(StoreError::Corrupt))
163 }
164 (ErrorClass::InvariantViolation, ErrorOrigin::Store) => {
165 Some(ErrorDetail::Store(StoreError::InvariantViolation))
166 }
167 _ => None,
168 };
169
170 Self {
171 class,
172 origin,
173 detail,
174 }
175 }
176
177 #[must_use]
179 pub const fn class(&self) -> ErrorClass {
180 self.class
181 }
182
183 #[must_use]
185 pub const fn origin(&self) -> ErrorOrigin {
186 self.origin
187 }
188
189 #[must_use]
191 pub const fn message(&self) -> &'static str {
192 compact_message_for(self.class, self.origin)
193 }
194
195 #[must_use]
197 pub const fn detail(&self) -> Option<&ErrorDetail> {
198 self.detail.as_ref()
199 }
200
201 #[must_use]
203 pub fn constraint_diagnostic(&self) -> Option<&ConstraintDiagnostic> {
204 match self.detail.as_ref() {
205 Some(ErrorDetail::Executor(detail)) => detail.constraint_diagnostic(),
206 Some(
207 ErrorDetail::Store(_)
208 | ErrorDetail::Query(_)
209 | ErrorDetail::Recovery(_)
210 | ErrorDetail::Serialize(_),
211 )
212 | None => None,
213 }
214 }
215
216 #[must_use]
218 pub fn diagnostic(&self) -> diagnostic_code::Diagnostic {
219 diagnostic_code::Diagnostic::new(
220 self.diagnostic_code(),
221 self.origin.diagnostic_origin(),
222 self.detail
223 .as_ref()
224 .and_then(ErrorDetail::diagnostic_detail),
225 )
226 }
227
228 #[must_use]
230 pub fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
231 self.detail.as_ref().map_or_else(
232 || self.class.diagnostic_code(self.origin),
233 ErrorDetail::diagnostic_code,
234 )
235 }
236
237 #[must_use]
239 pub fn into_message(self) -> String {
240 self.message().to_string()
241 }
242
243 #[cold]
245 #[inline(never)]
246 pub(crate) fn classified(class: ErrorClass, origin: ErrorOrigin) -> Self {
247 Self::new(class, origin)
248 }
249
250 #[cold]
254 #[inline(never)]
255 pub(crate) fn with_origin(self, origin: ErrorOrigin) -> Self {
256 Self::classified(self.class, origin)
257 }
258
259 #[cold]
261 #[inline(never)]
262 pub(crate) fn index_invariant() -> Self {
263 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Index)
264 }
265
266 pub(crate) fn index_key_field_count_exceeds_max(
268 _index_name: &str,
269 _field_count: usize,
270 _max_fields: usize,
271 ) -> Self {
272 Self::index_invariant()
273 }
274
275 pub(crate) fn index_expression_source_type_mismatch(
277 _index_name: &str,
278 _expression: impl Sized,
279 _expected: impl Sized,
280 _source_label: &str,
281 ) -> Self {
282 Self::index_invariant()
283 }
284
285 #[cold]
288 #[inline(never)]
289 #[cfg(any(test, feature = "query"))]
290 pub(crate) fn planner_executor_invariant() -> Self {
291 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Planner)
292 }
293
294 #[cold]
297 #[inline(never)]
298 pub(crate) fn query_executor_invariant() -> Self {
299 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Query)
300 }
301
302 #[cold]
305 #[inline(never)]
306 #[cfg(any(test, feature = "query"))]
307 pub(crate) fn cursor_executor_invariant() -> Self {
308 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Cursor)
309 }
310
311 #[cold]
313 #[inline(never)]
314 pub(crate) fn executor_invariant() -> Self {
315 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Executor)
316 }
317
318 #[cold]
320 #[inline(never)]
321 pub(crate) fn executor_internal() -> Self {
322 Self::new(ErrorClass::Internal, ErrorOrigin::Executor)
323 }
324
325 #[cold]
327 #[inline(never)]
328 pub(crate) fn executor_unsupported() -> Self {
329 Self::new(ErrorClass::Unsupported, ErrorOrigin::Executor)
330 }
331
332 pub(crate) fn mutation_database_owned_field_explicit(
334 _entity_path: &str,
335 _field_name: &str,
336 ) -> Self {
337 Self {
338 class: ErrorClass::Unsupported,
339 origin: ErrorOrigin::Executor,
340 detail: Some(ErrorDetail::Executor(
341 ExecutorErrorDetail::MutationDatabaseOwnedFieldExplicit,
342 )),
343 }
344 }
345
346 #[must_use]
348 pub fn mutation_required_field_missing(_entity_path: &str, _field_names: &str) -> Self {
349 Self {
350 class: ErrorClass::Unsupported,
351 origin: ErrorOrigin::Executor,
352 detail: Some(ErrorDetail::Executor(
353 ExecutorErrorDetail::MutationRequiredFieldMissing,
354 )),
355 }
356 }
357
358 #[must_use]
360 pub(crate) fn mutation_managed_timestamp_regression() -> Self {
361 Self {
362 class: ErrorClass::InvariantViolation,
363 origin: ErrorOrigin::Executor,
364 detail: Some(ErrorDetail::Executor(
365 ExecutorErrorDetail::MutationManagedTimestampRegression,
366 )),
367 }
368 }
369
370 pub(crate) fn mutation_constraint_violation(diagnostic: ConstraintDiagnostic) -> Self {
372 Self {
373 class: ErrorClass::InvariantViolation,
374 origin: ErrorOrigin::Executor,
375 detail: Some(ErrorDetail::Executor(
376 ExecutorErrorDetail::ConstraintViolation {
377 diagnostic: Box::new(diagnostic),
378 },
379 )),
380 }
381 }
382
383 pub(crate) fn accepted_row_constraint_program_corrupt() -> Self {
385 Self {
386 class: ErrorClass::Corruption,
387 origin: ErrorOrigin::Executor,
388 detail: Some(ErrorDetail::Executor(
389 ExecutorErrorDetail::AcceptedRowConstraintProgramCorrupt,
390 )),
391 }
392 }
393
394 pub(crate) fn mutation_constraint_activation_write_blocked(
396 diagnostic: ConstraintDiagnostic,
397 ) -> Self {
398 Self {
399 class: ErrorClass::Conflict,
400 origin: ErrorOrigin::Executor,
401 detail: Some(ErrorDetail::Executor(
402 ExecutorErrorDetail::ConstraintActivationWriteBlocked {
403 diagnostic: Box::new(diagnostic),
404 },
405 )),
406 }
407 }
408
409 pub(crate) fn mutation_structural_field_unknown(_entity_path: &str, _field_name: &str) -> Self {
411 Self::executor_invariant()
412 }
413
414 #[cfg(any(test, feature = "query"))]
416 pub(crate) fn scalar_page_cursor_boundary_order_required() -> Self {
417 Self::query_executor_invariant()
418 }
419
420 #[cfg(any(test, feature = "query"))]
422 pub(crate) fn scalar_page_cursor_boundary_after_ordering_required() -> Self {
423 Self::query_executor_invariant()
424 }
425
426 #[cfg(any(test, feature = "query"))]
428 pub(crate) fn scalar_page_pagination_after_ordering_required() -> Self {
429 Self::query_executor_invariant()
430 }
431
432 #[cfg(any(test, feature = "query"))]
434 pub(crate) fn fast_stream_route_kind_request_match_required() -> Self {
435 Self::query_executor_invariant()
436 }
437
438 #[cfg(any(test, feature = "query"))]
440 pub(crate) fn secondary_index_prefix_spec_required() -> Self {
441 Self::query_executor_invariant()
442 }
443
444 #[cfg(any(test, feature = "query"))]
446 pub(crate) fn index_range_limit_spec_required() -> Self {
447 Self::query_executor_invariant()
448 }
449
450 pub(crate) fn mutation_atomic_save_duplicate_key(_entity_path: &str, _key: impl Sized) -> Self {
452 Self {
453 class: ErrorClass::Conflict,
454 origin: ErrorOrigin::Executor,
455 detail: Some(ErrorDetail::Executor(
456 ExecutorErrorDetail::MutationBatchDuplicateKey,
457 )),
458 }
459 }
460
461 pub(crate) fn mutation_batch_empty() -> Self {
463 Self::mutation_batch_unsupported(ExecutorErrorDetail::MutationBatchEmpty)
464 }
465
466 pub(crate) fn mutation_batch_too_many_items() -> Self {
468 Self::mutation_batch_unsupported(ExecutorErrorDetail::MutationBatchTooManyItems)
469 }
470
471 pub(crate) fn mutation_batch_staged_bytes_exceeded() -> Self {
473 Self::mutation_batch_unsupported(ExecutorErrorDetail::MutationBatchStagedBytesExceeded)
474 }
475
476 pub(crate) fn mutation_batch_result_bytes_exceeded() -> Self {
478 Self::mutation_batch_unsupported(ExecutorErrorDetail::MutationBatchResultBytesExceeded)
479 }
480
481 pub(crate) fn mutation_batch_entity_mismatch() -> Self {
483 Self {
484 class: ErrorClass::Conflict,
485 origin: ErrorOrigin::Executor,
486 detail: Some(ErrorDetail::Executor(
487 ExecutorErrorDetail::MutationBatchEntityMismatch,
488 )),
489 }
490 }
491
492 fn mutation_batch_unsupported(detail: ExecutorErrorDetail) -> Self {
493 Self {
494 class: ErrorClass::Unsupported,
495 origin: ErrorOrigin::Executor,
496 detail: Some(ErrorDetail::Executor(detail)),
497 }
498 }
499
500 pub(crate) fn mutation_index_store_generation_changed(
502 _expected_generation: u64,
503 _observed_generation: u64,
504 ) -> Self {
505 Self::executor_invariant()
506 }
507
508 #[cold]
510 #[inline(never)]
511 #[cfg(any(test, feature = "query"))]
512 pub(crate) fn planner_invariant() -> Self {
513 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Planner)
514 }
515
516 #[cfg(any(test, feature = "query"))]
518 pub(crate) fn query_invalid_logical_plan() -> Self {
519 Self::planner_invariant()
520 }
521
522 pub(crate) fn store_invariant() -> Self {
524 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Store)
525 }
526
527 #[cold]
529 #[inline(never)]
530 pub(crate) fn store_internal() -> Self {
531 Self::new(ErrorClass::Internal, ErrorOrigin::Store)
532 }
533
534 pub(crate) fn commit_memory_id_unconfigured() -> Self {
536 Self::store_internal()
537 }
538
539 pub(crate) fn commit_store_uninitialized() -> Self {
541 Self::store_invariant()
542 }
543
544 pub(crate) fn commit_memory_id_mismatch(_cached_id: u8, _configured_id: u8) -> Self {
546 Self::store_internal()
547 }
548
549 pub(crate) fn commit_memory_stable_key_mismatch(
551 _cached_key: &str,
552 _configured_key: &str,
553 ) -> Self {
554 Self::store_internal()
555 }
556
557 pub(crate) fn database_incarnation_generation_failed() -> Self {
559 Self::store_internal()
560 }
561
562 pub(crate) fn database_incarnation_invalid() -> Self {
564 Self::store_corruption()
565 }
566
567 pub(crate) fn recovery_unsupported_database_format(found: Option<u16>, required: u16) -> Self {
569 Self {
570 class: ErrorClass::IncompatiblePersistedFormat,
571 origin: ErrorOrigin::Recovery,
572 detail: Some(ErrorDetail::Recovery(
573 RecoveryErrorDetail::UnsupportedFormatVersion { found, required },
574 )),
575 }
576 }
577
578 pub(crate) fn recovery_malformed_database_format_marker(
580 reason: RecoveryFormatMarkerError,
581 ) -> Self {
582 Self {
583 class: ErrorClass::Corruption,
584 origin: ErrorOrigin::Recovery,
585 detail: Some(ErrorDetail::Recovery(
586 RecoveryErrorDetail::MalformedFormatMarker { reason },
587 )),
588 }
589 }
590
591 pub(crate) fn recovery_database_format_control_unavailable() -> Self {
593 Self::new(ErrorClass::Internal, ErrorOrigin::Recovery)
594 }
595
596 pub(crate) fn commit_control_memory_growth_failed() -> Self {
598 Self::store_internal()
599 }
600
601 #[cfg(not(test))]
603 pub(crate) fn database_format_memory_registration_failed(_err: impl Sized) -> Self {
604 Self::store_internal()
605 }
606
607 pub(crate) fn recovery_effect_verification_failed() -> Self {
609 Self::store_corruption()
610 }
611
612 #[cold]
614 #[inline(never)]
615 pub(crate) fn index_internal() -> Self {
616 Self::new(ErrorClass::Internal, ErrorOrigin::Index)
617 }
618
619 pub(crate) fn structural_index_removal_entity_key_required() -> Self {
621 Self::index_internal()
622 }
623
624 pub(crate) fn structural_index_insertion_entity_key_required() -> Self {
626 Self::index_internal()
627 }
628
629 pub(crate) fn index_commit_op_old_entity_key_required() -> Self {
631 Self::index_internal()
632 }
633
634 pub(crate) fn index_commit_op_new_entity_key_required() -> Self {
636 Self::index_internal()
637 }
638
639 #[cfg(test)]
641 pub(crate) fn query_internal() -> Self {
642 Self::new(ErrorClass::Internal, ErrorOrigin::Query)
643 }
644
645 #[cold]
647 #[inline(never)]
648 #[cfg(any(test, feature = "query"))]
649 pub(crate) fn query_unsupported() -> Self {
650 Self::new(ErrorClass::Unsupported, ErrorOrigin::Query)
651 }
652
653 #[cold]
656 #[inline(never)]
657 #[cfg(any(test, feature = "query"))]
658 pub(crate) fn query_stale_accepted_schema_revision(
659 _expected_revision: u64,
660 _current_revision: Option<u64>,
661 ) -> Self {
662 Self {
663 class: ErrorClass::Conflict,
664 origin: ErrorOrigin::Query,
665 detail: Some(ErrorDetail::Query(QueryErrorDetail::StaleSchemaRevision)),
666 }
667 }
668
669 #[cold]
671 #[inline(never)]
672 #[cfg(feature = "sql")]
673 pub(crate) fn query_schema_ddl_admission(error: SchemaDdlAdmissionError) -> Self {
674 Self {
675 class: ErrorClass::Unsupported,
676 origin: ErrorOrigin::Query,
677 detail: Some(ErrorDetail::Query(QueryErrorDetail::SchemaDdlAdmission {
678 error,
679 })),
680 }
681 }
682
683 #[cold]
685 #[inline(never)]
686 #[cfg(any(test, feature = "query"))]
687 pub(crate) fn query_numeric_overflow() -> Self {
688 Self {
689 class: ErrorClass::Unsupported,
690 origin: ErrorOrigin::Query,
691 detail: Some(ErrorDetail::Query(QueryErrorDetail::NumericOverflow)),
692 }
693 }
694
695 #[cold]
698 #[inline(never)]
699 #[cfg(any(test, feature = "query"))]
700 pub(crate) fn query_numeric_not_representable() -> Self {
701 Self {
702 class: ErrorClass::Unsupported,
703 origin: ErrorOrigin::Query,
704 detail: Some(ErrorDetail::Query(
705 QueryErrorDetail::NumericNotRepresentable,
706 )),
707 }
708 }
709
710 #[cold]
712 #[inline(never)]
713 pub(crate) fn serialize_internal() -> Self {
714 Self::new(ErrorClass::Internal, ErrorOrigin::Serialize)
715 }
716
717 pub(crate) fn persisted_row_encode_failed(_detail: impl Sized) -> Self {
719 Self::persisted_row_encode_internal()
720 }
721
722 pub(crate) fn persisted_row_encode_internal() -> Self {
724 Self::serialize_internal()
725 }
726
727 pub(crate) fn persisted_row_field_encode_internal(_field_name: &str) -> Self {
729 Self::persisted_row_encode_internal()
730 }
731
732 #[cold]
734 #[inline(never)]
735 pub(crate) fn store_corruption() -> Self {
736 Self::new(ErrorClass::Corruption, ErrorOrigin::Store)
737 }
738
739 pub(crate) fn commit_corruption() -> Self {
741 Self::store_corruption()
742 }
743
744 pub(crate) fn commit_component_corruption() -> Self {
746 Self::commit_corruption()
747 }
748
749 pub(crate) fn commit_id_generation_failed() -> Self {
751 Self::store_internal()
752 }
753
754 pub(crate) fn commit_marker_payload_exceeds_u32_length_limit() -> Self {
756 Self::store_unsupported()
757 }
758
759 pub(crate) fn commit_component_length_invalid() -> Self {
761 Self::commit_corruption()
762 }
763
764 pub(crate) fn commit_marker_exceeds_max_size() -> Self {
766 Self::commit_corruption()
767 }
768
769 pub(crate) fn commit_control_slot_exceeds_max_size() -> Self {
771 Self::store_unsupported()
772 }
773
774 pub(crate) fn commit_control_slot_marker_bytes_exceed_u32_length_limit() -> Self {
776 Self::store_unsupported()
777 }
778
779 pub(crate) fn startup_index_rebuild_invalid_data_key() -> Self {
781 Self::store_corruption()
782 }
783
784 #[cold]
786 #[inline(never)]
787 pub(crate) fn index_corruption() -> Self {
788 Self::new(ErrorClass::Corruption, ErrorOrigin::Index)
789 }
790
791 pub(crate) fn index_unique_validation_corruption() -> Self {
793 Self::index_plan_index_corruption()
794 }
795
796 pub(crate) fn structural_index_entry_corruption() -> Self {
798 Self::index_plan_index_corruption()
799 }
800
801 pub(crate) fn index_unique_validation_entity_key_required() -> Self {
803 Self::index_invariant()
804 }
805
806 pub(crate) fn index_unique_validation_row_deserialize_failed() -> Self {
808 Self::index_plan_serialize_corruption()
809 }
810
811 pub(crate) fn index_unique_validation_primary_key_decode_failed() -> Self {
813 Self::index_plan_serialize_corruption()
814 }
815
816 pub(crate) fn index_unique_validation_key_rebuild_failed() -> Self {
818 Self::index_plan_serialize_corruption()
819 }
820
821 pub(crate) fn index_unique_validation_row_required() -> Self {
823 Self::index_plan_store_corruption()
824 }
825
826 #[cfg(any(test, feature = "query"))]
828 pub(crate) fn index_only_predicate_component_required() -> Self {
829 Self::index_invariant()
830 }
831
832 #[cfg(any(test, feature = "query"))]
834 pub(crate) fn index_scan_continuation_anchor_within_envelope_required() -> Self {
835 Self::index_invariant()
836 }
837
838 #[cfg(any(test, feature = "query"))]
840 pub(crate) fn index_scan_continuation_advancement_required() -> Self {
841 Self::index_invariant()
842 }
843
844 #[cfg(any(test, feature = "query"))]
846 pub(crate) fn index_scan_key_corrupted_during(
847 _context: &'static str,
848 _err: impl Sized,
849 ) -> Self {
850 Self::index_corruption()
851 }
852
853 #[cfg(any(test, feature = "query"))]
855 pub(crate) fn index_projection_component_required(
856 _index_name: &str,
857 _component_index: usize,
858 ) -> Self {
859 Self::index_invariant()
860 }
861
862 #[cfg(any(test, feature = "query"))]
864 pub(crate) fn index_entry_decode_failed() -> Self {
865 Self::index_corruption()
866 }
867
868 pub(crate) fn serialize_corruption() -> Self {
870 Self::new(ErrorClass::Corruption, ErrorOrigin::Serialize)
871 }
872
873 pub(crate) fn persisted_row_decode_corruption() -> Self {
875 Self::serialize_corruption()
876 }
877
878 pub(crate) fn persisted_row_layout_outside_accepted_window() -> Self {
880 Self {
881 class: ErrorClass::Corruption,
882 origin: ErrorOrigin::Serialize,
883 detail: Some(ErrorDetail::Serialize(
884 SerializeErrorDetail::PersistedRowLayoutOutsideAcceptedWindow,
885 )),
886 }
887 }
888
889 pub(crate) fn persisted_row_slot_count_mismatch() -> Self {
891 Self {
892 class: ErrorClass::Corruption,
893 origin: ErrorOrigin::Serialize,
894 detail: Some(ErrorDetail::Serialize(
895 SerializeErrorDetail::PersistedRowSlotCountMismatch,
896 )),
897 }
898 }
899
900 pub(crate) fn persisted_row_field_decode_failed(field_name: &str, _detail: impl Sized) -> Self {
902 Self::persisted_row_field_decode_corruption(field_name)
903 }
904
905 pub(crate) fn persisted_row_field_decode_corruption(_field_name: &str) -> Self {
907 Self::persisted_row_decode_corruption()
908 }
909
910 pub(crate) fn persisted_row_field_kind_decode_failed(
912 field_name: &str,
913 _field_kind: impl fmt::Debug,
914 _detail: impl Sized,
915 ) -> Self {
916 Self::persisted_row_field_decode_corruption(field_name)
917 }
918
919 pub(crate) fn persisted_row_field_payload_exact_len_required(field_name: &str) -> Self {
921 Self::persisted_row_field_decode_corruption(field_name)
922 }
923
924 pub(crate) fn persisted_row_field_payload_must_be_empty(field_name: &str) -> Self {
926 Self::persisted_row_field_decode_corruption(field_name)
927 }
928
929 pub(crate) fn persisted_row_field_payload_invalid_byte(field_name: &str) -> Self {
931 Self::persisted_row_field_decode_corruption(field_name)
932 }
933
934 pub(crate) fn persisted_row_field_payload_non_finite(field_name: &str) -> Self {
936 Self::persisted_row_field_decode_corruption(field_name)
937 }
938
939 pub(crate) fn persisted_row_field_text_payload_invalid_utf8(field_name: &str) -> Self {
941 Self::persisted_row_field_decode_corruption(field_name)
942 }
943
944 pub(crate) fn persisted_row_slot_lookup_out_of_bounds(_model_path: &str, _slot: usize) -> Self {
946 Self::index_invariant()
947 }
948
949 pub(crate) fn persisted_row_slot_cache_lookup_out_of_bounds(
951 _model_path: &str,
952 _slot: usize,
953 ) -> Self {
954 Self::index_invariant()
955 }
956
957 pub(crate) fn persisted_row_primary_key_not_primary_key_encodable(
959 _data_key: impl fmt::Debug,
960 _detail: impl Sized,
961 ) -> Self {
962 Self::persisted_row_decode_corruption()
963 }
964
965 pub(crate) fn persisted_row_primary_key_slot_missing(_data_key: impl fmt::Debug) -> Self {
967 Self::persisted_row_decode_corruption()
968 }
969
970 pub(crate) fn persisted_row_key_mismatch() -> Self {
972 Self::store_corruption()
973 }
974
975 pub(crate) fn persisted_row_declared_field_missing(field_name: &str) -> Self {
977 Self::persisted_row_field_decode_corruption(field_name)
978 }
979
980 pub(crate) fn reverse_index_ordinal_overflow(
982 _source_path: &str,
983 _field_name: &str,
984 _target_path: &str,
985 _detail: impl Sized,
986 ) -> Self {
987 Self::index_internal()
988 }
989
990 pub(crate) fn reverse_index_entry_corrupted(
992 _source_path: &str,
993 _field_name: &str,
994 _target_path: &str,
995 _index_key: impl fmt::Debug,
996 _detail: impl Sized,
997 ) -> Self {
998 Self::index_corruption()
999 }
1000
1001 pub(crate) fn relation_target_store_missing(
1003 _source_path: &str,
1004 _field_name: &str,
1005 _target_path: &str,
1006 _store_path: &str,
1007 _detail: impl Sized,
1008 ) -> Self {
1009 Self::executor_internal()
1010 }
1011
1012 pub(crate) fn relation_target_key_decode_failed(
1014 _context_label: &str,
1015 _source_path: &str,
1016 _field_name: &str,
1017 _target_path: &str,
1018 _detail: impl Sized,
1019 ) -> Self {
1020 Self::identity_corruption()
1021 }
1022
1023 pub(crate) fn relation_target_entity_mismatch(
1025 _context_label: &str,
1026 _source_path: &str,
1027 _field_name: &str,
1028 _target_path: &str,
1029 _target_entity_name: &str,
1030 _expected_tag: impl Sized,
1031 _actual_tag: impl Sized,
1032 ) -> Self {
1033 Self::store_corruption()
1034 }
1035
1036 pub(crate) fn relation_source_row_decode_failed(
1038 _source_path: &str,
1039 _field_name: &str,
1040 _target_path: &str,
1041 _detail: impl Sized,
1042 ) -> Self {
1043 Self::persisted_row_decode_corruption()
1044 }
1045
1046 pub(crate) fn relation_source_row_unsupported_scalar_relation_key(
1048 _source_path: &str,
1049 _field_name: &str,
1050 _target_path: &str,
1051 ) -> Self {
1052 Self::persisted_row_decode_corruption()
1053 }
1054
1055 pub(crate) fn relation_source_row_unsupported_key_kind(_field_kind: impl fmt::Debug) -> Self {
1057 Self::persisted_row_decode_corruption()
1058 }
1059
1060 #[cfg(any(test, feature = "query"))]
1062 pub(crate) fn bytes_covering_component_payload_empty() -> Self {
1063 Self::index_corruption()
1064 }
1065
1066 #[cfg(any(test, feature = "query"))]
1068 pub(crate) fn bytes_covering_bool_payload_truncated() -> Self {
1069 Self::index_corruption()
1070 }
1071
1072 #[cfg(any(test, feature = "query"))]
1074 pub(crate) fn bytes_covering_component_payload_invalid_length() -> Self {
1075 Self::index_corruption()
1076 }
1077
1078 #[cfg(any(test, feature = "query"))]
1080 pub(crate) fn bytes_covering_bool_payload_invalid_value() -> Self {
1081 Self::index_corruption()
1082 }
1083
1084 #[cfg(any(test, feature = "query"))]
1086 pub(crate) fn bytes_covering_text_payload_invalid_terminator() -> Self {
1087 Self::index_corruption()
1088 }
1089
1090 #[cfg(any(test, feature = "query"))]
1092 pub(crate) fn bytes_covering_text_payload_trailing_bytes() -> Self {
1093 Self::index_corruption()
1094 }
1095
1096 #[cfg(any(test, feature = "query"))]
1098 pub(crate) fn bytes_covering_text_payload_invalid_utf8() -> Self {
1099 Self::index_corruption()
1100 }
1101
1102 #[cfg(any(test, feature = "query"))]
1104 pub(crate) fn bytes_covering_text_payload_invalid_escape_byte() -> Self {
1105 Self::index_corruption()
1106 }
1107
1108 #[cfg(any(test, feature = "query"))]
1110 pub(crate) fn bytes_covering_text_payload_missing_terminator() -> Self {
1111 Self::index_corruption()
1112 }
1113
1114 #[must_use]
1116 pub fn missing_persisted_slot(field_name: &'static str) -> Self {
1117 Self::persisted_row_field_decode_corruption(field_name)
1118 }
1119
1120 pub(crate) fn identity_corruption() -> Self {
1122 Self::new(ErrorClass::Corruption, ErrorOrigin::Identity)
1123 }
1124
1125 pub(crate) fn identity_state_corruption() -> Self {
1127 Self::identity_corruption()
1128 }
1129
1130 pub(crate) fn identity_state_conflict() -> Self {
1132 Self::new(ErrorClass::Conflict, ErrorOrigin::Identity)
1133 }
1134
1135 pub(crate) fn identity_state_capacity_exhausted() -> Self {
1137 Self::new(ErrorClass::Unsupported, ErrorOrigin::Identity)
1138 }
1139
1140 pub(crate) fn identity_exhausted() -> Self {
1142 Self::new(ErrorClass::Unsupported, ErrorOrigin::Identity)
1143 }
1144
1145 pub(crate) fn identity_candidate_count_exhausted() -> Self {
1147 Self::new(ErrorClass::Unsupported, ErrorOrigin::Identity)
1148 }
1149
1150 #[cold]
1152 #[inline(never)]
1153 pub(crate) fn store_unsupported() -> Self {
1154 Self::new(ErrorClass::Unsupported, ErrorOrigin::Store)
1155 }
1156
1157 pub(crate) fn schema_application_conflict() -> Self {
1159 Self::new(ErrorClass::Conflict, ErrorOrigin::Store)
1160 }
1161
1162 #[cfg(any(test, feature = "query"))]
1164 pub(crate) fn schema_ddl_publication_race_lost(_entity_path: &str) -> Self {
1165 Self {
1166 class: ErrorClass::Unsupported,
1167 origin: ErrorOrigin::Store,
1168 detail: Some(ErrorDetail::Store(StoreError::SchemaDdlPublicationRaceLost)),
1169 }
1170 }
1171
1172 #[cfg(feature = "sql")]
1174 pub(crate) fn schema_ddl_rewrite_requires_migration(_entity_path: &str) -> Self {
1175 Self {
1176 class: ErrorClass::Unsupported,
1177 origin: ErrorOrigin::Store,
1178 detail: Some(ErrorDetail::Store(
1179 StoreError::SchemaDdlRewriteRequiresMigration,
1180 )),
1181 }
1182 }
1183
1184 pub(crate) fn journal_mutation_revision_exhausted() -> Self {
1186 Self {
1187 class: ErrorClass::Unsupported,
1188 origin: ErrorOrigin::Store,
1189 detail: Some(ErrorDetail::Store(
1190 StoreError::JournalMutationRevisionExhausted,
1191 )),
1192 }
1193 }
1194
1195 pub(crate) fn schema_transition_budget_exceeded(
1197 resource: SchemaTransitionBudgetResource,
1198 ) -> Self {
1199 Self {
1200 class: ErrorClass::Unsupported,
1201 origin: ErrorOrigin::Store,
1202 detail: Some(ErrorDetail::Store(
1203 StoreError::SchemaTransitionBudgetExceeded { resource },
1204 )),
1205 }
1206 }
1207
1208 pub(crate) fn unsupported_entity_tag_in_data_store(
1210 _entity_tag: crate::types::EntityTag,
1211 ) -> Self {
1212 Self::store_unsupported()
1213 }
1214
1215 #[cfg(not(test))]
1217 pub(crate) fn commit_memory_id_registration_failed(_err: impl Sized) -> Self {
1218 Self::store_internal()
1219 }
1220
1221 pub(crate) fn index_unsupported() -> Self {
1223 Self::new(ErrorClass::Unsupported, ErrorOrigin::Index)
1224 }
1225
1226 pub(crate) fn index_component_exceeds_max_size() -> Self {
1228 Self::index_unsupported()
1229 }
1230
1231 pub(crate) fn serialize_unsupported() -> Self {
1233 Self::new(ErrorClass::Unsupported, ErrorOrigin::Serialize)
1234 }
1235
1236 #[cfg(any(test, feature = "query"))]
1238 pub(crate) fn cursor_invalid_continuation() -> Self {
1239 Self::new(ErrorClass::Unsupported, ErrorOrigin::Cursor)
1240 }
1241
1242 pub(crate) fn serialize_incompatible_persisted_format() -> Self {
1244 Self::new(
1245 ErrorClass::IncompatiblePersistedFormat,
1246 ErrorOrigin::Serialize,
1247 )
1248 }
1249
1250 #[cfg(feature = "sql")]
1253 pub(crate) fn query_unsupported_sql_feature(feature: diagnostic_code::SqlFeatureCode) -> Self {
1254 Self {
1255 class: ErrorClass::Unsupported,
1256 origin: ErrorOrigin::Query,
1257 detail: Some(ErrorDetail::Query(
1258 QueryErrorDetail::UnsupportedSqlFeature { feature },
1259 )),
1260 }
1261 }
1262
1263 #[cfg(feature = "sql")]
1266 pub(crate) fn query_sql_lowering(reason: diagnostic_code::SqlLoweringCode) -> Self {
1267 Self {
1268 class: ErrorClass::Unsupported,
1269 origin: ErrorOrigin::Query,
1270 detail: Some(ErrorDetail::Query(QueryErrorDetail::SqlLowering { reason })),
1271 }
1272 }
1273
1274 #[cfg(any(test, feature = "query"))]
1277 pub(crate) fn query_unsupported_projection(
1278 reason: diagnostic_code::QueryProjectionCode,
1279 ) -> Self {
1280 Self {
1281 class: ErrorClass::Unsupported,
1282 origin: ErrorOrigin::Query,
1283 detail: Some(ErrorDetail::Query(
1284 QueryErrorDetail::UnsupportedProjection { reason },
1285 )),
1286 }
1287 }
1288
1289 #[cfg(any(test, feature = "query"))]
1291 pub(crate) fn query_unknown_aggregate_target_field() -> Self {
1292 Self {
1293 class: ErrorClass::Unsupported,
1294 origin: ErrorOrigin::Query,
1295 detail: Some(ErrorDetail::Query(
1296 QueryErrorDetail::UnknownAggregateTargetField,
1297 )),
1298 }
1299 }
1300
1301 #[cfg(feature = "sql")]
1304 pub(crate) fn query_sql_surface_mismatch(
1305 mismatch: diagnostic_code::SqlSurfaceMismatchCode,
1306 ) -> Self {
1307 Self {
1308 class: ErrorClass::Unsupported,
1309 origin: ErrorOrigin::Query,
1310 detail: Some(ErrorDetail::Query(QueryErrorDetail::SqlSurfaceMismatch {
1311 mismatch,
1312 })),
1313 }
1314 }
1315
1316 pub(crate) fn query_sql_write_boundary(
1318 boundary: diagnostic_code::SqlWriteBoundaryCode,
1319 ) -> Self {
1320 Self {
1321 class: ErrorClass::Unsupported,
1322 origin: ErrorOrigin::Query,
1323 detail: Some(ErrorDetail::Query(QueryErrorDetail::SqlWriteBoundary {
1324 boundary,
1325 })),
1326 }
1327 }
1328
1329 pub fn store_not_found(_key: impl Sized) -> Self {
1330 Self {
1331 class: ErrorClass::NotFound,
1332 origin: ErrorOrigin::Store,
1333 detail: Some(ErrorDetail::Store(StoreError::NotFound)),
1334 }
1335 }
1336
1337 pub fn unsupported_entity_path(_path: impl Sized) -> Self {
1339 Self::store_unsupported()
1340 }
1341
1342 #[must_use]
1343 pub const fn is_not_found(&self) -> bool {
1344 matches!(self.detail, Some(ErrorDetail::Store(StoreError::NotFound)))
1345 }
1346
1347 #[cold]
1349 #[inline(never)]
1350 pub(crate) fn index_plan_corruption(origin: ErrorOrigin) -> Self {
1351 Self::new(ErrorClass::Corruption, origin)
1352 }
1353
1354 #[cold]
1356 #[inline(never)]
1357 pub(crate) fn index_plan_index_corruption() -> Self {
1358 Self::index_plan_corruption(ErrorOrigin::Index)
1359 }
1360
1361 #[cold]
1363 #[inline(never)]
1364 pub(crate) fn index_plan_store_corruption() -> Self {
1365 Self::index_plan_corruption(ErrorOrigin::Store)
1366 }
1367
1368 #[cold]
1370 #[inline(never)]
1371 pub(crate) fn index_plan_serialize_corruption() -> Self {
1372 Self::index_plan_corruption(ErrorOrigin::Serialize)
1373 }
1374
1375 #[cfg(test)]
1377 pub(crate) fn index_plan_invariant(origin: ErrorOrigin) -> Self {
1378 Self::new(ErrorClass::InvariantViolation, origin)
1379 }
1380
1381 #[cfg(test)]
1383 pub(crate) fn index_plan_store_invariant() -> Self {
1384 Self::index_plan_invariant(ErrorOrigin::Store)
1385 }
1386
1387 pub(crate) fn index_conflict() -> Self {
1393 Self::new(ErrorClass::Conflict, ErrorOrigin::Index)
1394 }
1395}
1396
1397impl From<diagnostic_code::QueryReadAdmissionCode> for InternalError {
1398 fn from(reason: diagnostic_code::QueryReadAdmissionCode) -> Self {
1399 Self {
1400 class: ErrorClass::Unsupported,
1401 origin: ErrorOrigin::Query,
1402 detail: Some(ErrorDetail::Query(QueryErrorDetail::QueryReadAdmission {
1403 reason,
1404 })),
1405 }
1406 }
1407}
1408
1409impl fmt::Debug for InternalError {
1410 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1411 fmt_compact_diagnostic(
1412 f,
1413 self.diagnostic_code(),
1414 self.detail
1415 .as_ref()
1416 .and_then(ErrorDetail::diagnostic_detail),
1417 )
1418 }
1419}
1420
1421impl fmt::Display for InternalError {
1422 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1423 f.write_str(self.message())
1424 }
1425}
1426
1427impl std::error::Error for InternalError {}
1428
1429#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq)]
1437pub enum ConstraintDiagnosticKind {
1438 Check,
1440
1441 NotNull,
1443
1444 Relation,
1446
1447 TargetedRule,
1449
1450 Unique,
1452}
1453
1454impl ConstraintDiagnosticKind {
1455 #[must_use]
1457 pub const fn as_str(self) -> &'static str {
1458 match self {
1459 Self::Check => "check",
1460 Self::NotNull => "not_null",
1461 Self::Relation => "relation",
1462 Self::TargetedRule => "targeted_rule",
1463 Self::Unique => "unique",
1464 }
1465 }
1466}
1467
1468#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq)]
1477pub enum ConstraintValuePathComponent {
1478 RootField { field_id: u32 },
1480
1481 RecordMember {
1483 composite_type_id: u32,
1484 member_id: u32,
1485 },
1486
1487 TupleElement {
1489 composite_type_id: u32,
1490 ordinal: u32,
1491 },
1492
1493 Newtype { composite_type_id: u32 },
1495
1496 EnumVariant { enum_type_id: u32, variant_id: u32 },
1498
1499 ListElement { index: u32 },
1501
1502 SetElement { index: u32 },
1504
1505 MapEntryKey { index: u32 },
1507
1508 MapEntryValue { index: u32 },
1510}
1511
1512impl fmt::Display for ConstraintValuePathComponent {
1513 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1514 match self {
1515 Self::RootField { field_id } => write!(f, "field#{field_id}"),
1516 Self::RecordMember {
1517 composite_type_id,
1518 member_id,
1519 } => write!(f, "record#{composite_type_id}.member#{member_id}"),
1520 Self::TupleElement {
1521 composite_type_id,
1522 ordinal,
1523 } => write!(f, "tuple#{composite_type_id}[{ordinal}]"),
1524 Self::Newtype { composite_type_id } => write!(f, "newtype#{composite_type_id}"),
1525 Self::EnumVariant {
1526 enum_type_id,
1527 variant_id,
1528 } => write!(f, "enum#{enum_type_id}.variant#{variant_id}"),
1529 Self::ListElement { index } => write!(f, "list[{index}]"),
1530 Self::SetElement { index } => write!(f, "set[{index}]"),
1531 Self::MapEntryKey { index } => write!(f, "map[{index}].key"),
1532 Self::MapEntryValue { index } => write!(f, "map[{index}].value"),
1533 }
1534 }
1535}
1536
1537#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
1544pub struct ConstraintValuePath {
1545 components: Vec<ConstraintValuePathComponent>,
1546}
1547
1548impl ConstraintValuePath {
1549 #[must_use]
1551 pub(crate) const fn new(components: Vec<ConstraintValuePathComponent>) -> Self {
1552 Self { components }
1553 }
1554
1555 #[must_use]
1557 pub const fn components(&self) -> &[ConstraintValuePathComponent] {
1558 self.components.as_slice()
1559 }
1560}
1561
1562impl fmt::Display for ConstraintValuePath {
1563 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1564 for (ordinal, component) in self.components.iter().enumerate() {
1565 if ordinal != 0 {
1566 f.write_str("/")?;
1567 }
1568 component.fmt(f)?;
1569 }
1570 Ok(())
1571 }
1572}
1573
1574#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq)]
1582pub enum ConstraintDiagnosticContext {
1583 Integrity,
1585
1586 MigrationValidation,
1588
1589 WriteAdmission,
1591}
1592
1593impl ConstraintDiagnosticContext {
1594 #[must_use]
1596 pub const fn as_str(self) -> &'static str {
1597 match self {
1598 Self::Integrity => "integrity",
1599 Self::MigrationValidation => "migration_validation",
1600 Self::WriteAdmission => "write_admission",
1601 }
1602 }
1603}
1604
1605#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
1614pub struct ConstraintDiagnostic {
1615 constraint_id: u32,
1616 constraint_name: String,
1617 constraint_kind: ConstraintDiagnosticKind,
1618 entity: String,
1619 primary_key: Option<Vec<u8>>,
1620 field_paths: Vec<String>,
1621 value_path: Option<Box<ConstraintValuePath>>,
1622 context: ConstraintDiagnosticContext,
1623 error_code: u16,
1624}
1625
1626impl ConstraintDiagnostic {
1627 #[must_use]
1629 pub(crate) const fn write_violation(
1630 constraint_id: u32,
1631 constraint_name: String,
1632 constraint_kind: ConstraintDiagnosticKind,
1633 entity: String,
1634 primary_key: Option<Vec<u8>>,
1635 field_paths: Vec<String>,
1636 ) -> Self {
1637 Self {
1638 constraint_id,
1639 constraint_name,
1640 constraint_kind,
1641 entity,
1642 primary_key,
1643 field_paths,
1644 value_path: None,
1645 context: ConstraintDiagnosticContext::WriteAdmission,
1646 error_code: diagnostic_code::ErrorCode::RUNTIME_BOUNDARY_CONSTRAINT_VIOLATION.raw(),
1647 }
1648 }
1649
1650 #[must_use]
1652 pub(crate) fn write_targeted_rule_violation(
1653 constraint_id: u32,
1654 constraint_name: String,
1655 entity: String,
1656 primary_key: Option<Vec<u8>>,
1657 field_paths: Vec<String>,
1658 value_path: ConstraintValuePath,
1659 ) -> Self {
1660 Self {
1661 constraint_id,
1662 constraint_name,
1663 constraint_kind: ConstraintDiagnosticKind::TargetedRule,
1664 entity,
1665 primary_key,
1666 field_paths,
1667 value_path: Some(Box::new(value_path)),
1668 context: ConstraintDiagnosticContext::WriteAdmission,
1669 error_code: diagnostic_code::ErrorCode::RUNTIME_BOUNDARY_CONSTRAINT_VIOLATION.raw(),
1670 }
1671 }
1672
1673 #[must_use]
1675 pub(crate) const fn write_activation_blocked(
1676 constraint_id: u32,
1677 constraint_name: String,
1678 constraint_kind: ConstraintDiagnosticKind,
1679 entity: String,
1680 primary_key: Option<Vec<u8>>,
1681 field_paths: Vec<String>,
1682 ) -> Self {
1683 Self {
1684 constraint_id,
1685 constraint_name,
1686 constraint_kind,
1687 entity,
1688 primary_key,
1689 field_paths,
1690 value_path: None,
1691 context: ConstraintDiagnosticContext::WriteAdmission,
1692 error_code:
1693 diagnostic_code::ErrorCode::RUNTIME_BOUNDARY_CONSTRAINT_ACTIVATION_WRITE_BLOCKED
1694 .raw(),
1695 }
1696 }
1697
1698 #[must_use]
1700 pub(crate) const fn migration_validation(
1701 constraint_id: u32,
1702 constraint_name: String,
1703 constraint_kind: ConstraintDiagnosticKind,
1704 entity: String,
1705 primary_key: Vec<u8>,
1706 field_paths: Vec<String>,
1707 error_code: u16,
1708 ) -> Self {
1709 Self {
1710 constraint_id,
1711 constraint_name,
1712 constraint_kind,
1713 entity,
1714 primary_key: Some(primary_key),
1715 field_paths,
1716 value_path: None,
1717 context: ConstraintDiagnosticContext::MigrationValidation,
1718 error_code,
1719 }
1720 }
1721
1722 #[must_use]
1724 pub(crate) fn migration_targeted_rule_validation(
1725 constraint_id: u32,
1726 constraint_name: String,
1727 entity: String,
1728 primary_key: Vec<u8>,
1729 field_paths: Vec<String>,
1730 value_path: ConstraintValuePath,
1731 error_code: u16,
1732 ) -> Self {
1733 Self {
1734 constraint_id,
1735 constraint_name,
1736 constraint_kind: ConstraintDiagnosticKind::TargetedRule,
1737 entity,
1738 primary_key: Some(primary_key),
1739 field_paths,
1740 value_path: Some(Box::new(value_path)),
1741 context: ConstraintDiagnosticContext::MigrationValidation,
1742 error_code,
1743 }
1744 }
1745
1746 #[must_use]
1748 pub const fn constraint_id(&self) -> u32 {
1749 self.constraint_id
1750 }
1751
1752 #[must_use]
1754 pub const fn constraint_name(&self) -> &str {
1755 self.constraint_name.as_str()
1756 }
1757
1758 #[must_use]
1760 pub const fn constraint_kind(&self) -> ConstraintDiagnosticKind {
1761 self.constraint_kind
1762 }
1763
1764 #[must_use]
1766 pub const fn entity(&self) -> &str {
1767 self.entity.as_str()
1768 }
1769
1770 #[must_use]
1772 pub fn primary_key(&self) -> Option<&[u8]> {
1773 self.primary_key.as_deref()
1774 }
1775
1776 #[must_use]
1778 pub const fn field_paths(&self) -> &[String] {
1779 self.field_paths.as_slice()
1780 }
1781
1782 #[must_use]
1784 pub fn value_path(&self) -> Option<&ConstraintValuePath> {
1785 self.value_path.as_deref()
1786 }
1787
1788 #[must_use]
1790 pub const fn context(&self) -> ConstraintDiagnosticContext {
1791 self.context
1792 }
1793
1794 #[must_use]
1796 pub const fn error_code(&self) -> diagnostic_code::ErrorCode {
1797 diagnostic_code::ErrorCode::from_raw(self.error_code)
1798 }
1799
1800 #[must_use]
1802 pub const fn error_class(&self) -> diagnostic_code::ErrorClass {
1803 self.error_code().class()
1804 }
1805}
1806
1807pub enum ErrorDetail {
1815 Executor(ExecutorErrorDetail),
1817 Store(StoreError),
1818 Query(QueryErrorDetail),
1819 Recovery(RecoveryErrorDetail),
1820 Serialize(SerializeErrorDetail),
1822 }
1825
1826pub enum ExecutorErrorDetail {
1828 MutationRequiredFieldMissing,
1830 MutationManagedTimestampRegression,
1832 MutationDatabaseOwnedFieldExplicit,
1834 MutationBatchEmpty,
1836 MutationBatchTooManyItems,
1838 MutationBatchStagedBytesExceeded,
1840 MutationBatchResultBytesExceeded,
1842 MutationBatchEntityMismatch,
1844 MutationBatchDuplicateKey,
1846 ConstraintViolation {
1848 diagnostic: Box<ConstraintDiagnostic>,
1849 },
1850 AcceptedRowConstraintProgramCorrupt,
1852 ConstraintActivationWriteBlocked {
1854 diagnostic: Box<ConstraintDiagnostic>,
1855 },
1856}
1857
1858impl ExecutorErrorDetail {
1859 #[must_use]
1861 pub fn constraint_diagnostic(&self) -> Option<&ConstraintDiagnostic> {
1862 match self {
1863 Self::ConstraintActivationWriteBlocked { diagnostic }
1864 | Self::ConstraintViolation { diagnostic } => Some(diagnostic.as_ref()),
1865 Self::MutationRequiredFieldMissing
1866 | Self::MutationManagedTimestampRegression
1867 | Self::MutationDatabaseOwnedFieldExplicit
1868 | Self::MutationBatchEmpty
1869 | Self::MutationBatchTooManyItems
1870 | Self::MutationBatchStagedBytesExceeded
1871 | Self::MutationBatchResultBytesExceeded
1872 | Self::MutationBatchEntityMismatch
1873 | Self::MutationBatchDuplicateKey
1874 | Self::AcceptedRowConstraintProgramCorrupt => None,
1875 }
1876 }
1877}
1878
1879pub enum SerializeErrorDetail {
1881 PersistedRowLayoutOutsideAcceptedWindow,
1883
1884 PersistedRowSlotCountMismatch,
1886}
1887
1888pub enum RecoveryErrorDetail {
1895 UnsupportedFormatVersion { found: Option<u16>, required: u16 },
1896
1897 MalformedFormatMarker { reason: RecoveryFormatMarkerError },
1898}
1899
1900#[derive(Clone, Copy, Eq, PartialEq)]
1902pub enum RecoveryFormatMarkerError {
1903 Magic,
1904 Checksum,
1905 State,
1906}
1907
1908pub enum StoreError {
1916 NotFound,
1917
1918 Corrupt,
1919
1920 InvariantViolation,
1921
1922 SchemaDdlPublicationRaceLost,
1923
1924 SchemaDdlRewriteRequiresMigration,
1925
1926 SchemaRowLayoutVersionExhausted,
1927
1928 JournalMutationRevisionExhausted,
1929
1930 SchemaTransitionBudgetExceeded {
1931 resource: SchemaTransitionBudgetResource,
1932 },
1933
1934 SchemaGeneratedFieldAfterDdlField,
1936
1937 SchemaGeneratedConstraintActivationStale,
1939}
1940
1941pub enum QueryErrorDetail {
1948 NumericOverflow,
1949
1950 NumericNotRepresentable,
1951
1952 UnsupportedSqlFeature {
1953 feature: diagnostic_code::SqlFeatureCode,
1954 },
1955
1956 SqlLowering {
1957 reason: diagnostic_code::SqlLoweringCode,
1958 },
1959
1960 UnsupportedProjection {
1961 reason: diagnostic_code::QueryProjectionCode,
1962 },
1963
1964 UnknownAggregateTargetField,
1965
1966 ResultShapeMismatch {
1967 reason: diagnostic_code::QueryResultShapeCode,
1968 },
1969
1970 QueryReadAdmission {
1971 reason: diagnostic_code::QueryReadAdmissionCode,
1972 },
1973
1974 SqlSurfaceMismatch {
1975 mismatch: diagnostic_code::SqlSurfaceMismatchCode,
1976 },
1977
1978 SqlWriteBoundary {
1979 boundary: diagnostic_code::SqlWriteBoundaryCode,
1980 },
1981
1982 SchemaDdlAdmission {
1983 error: SchemaDdlAdmissionError,
1984 },
1985
1986 StaleSchemaRevision,
1987}
1988
1989impl fmt::Display for QueryErrorDetail {
1990 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1991 f.write_str(COMPACT_QUERY_DIAGNOSTIC_MESSAGE)
1992 }
1993}
1994
1995impl std::error::Error for QueryErrorDetail {}
1996
1997#[derive(Clone, Copy, Debug, Eq, PartialEq)]
2005pub enum SchemaTransitionBudgetResource {
2006 DeletionKeys,
2008 ProjectionEntries,
2010 ProjectionWorkUnits,
2012 SourceRows,
2014 SourceRowBytes,
2016 StagedRawBytes,
2018}
2019
2020#[derive(Clone, Copy, Eq, PartialEq)]
2029pub enum SchemaDdlAdmissionError {
2030 MissingExpectedSchemaVersion,
2031
2032 MissingNextSchemaVersion,
2033
2034 StaleExpectedSchemaVersion,
2035
2036 InvalidExpectedSchemaVersion,
2037
2038 InvalidNextSchemaVersion,
2039
2040 AcceptedSchemaChangeWithoutVersionBump,
2041
2042 EmptyVersionBump,
2043
2044 VersionGap,
2045
2046 VersionRollback,
2047
2048 FingerprintMethodMismatch,
2049
2050 UnsupportedTransitionClass,
2051
2052 PhysicalRunnerMissing,
2053
2054 ValidationFailed,
2055
2056 PublicationRaceLost,
2057
2058 InvalidAddColumnDefault,
2059
2060 InvalidAlterColumnDefault,
2061
2062 RowLayoutVersionExhausted,
2063
2064 GeneratedIndexDropRejected,
2065
2066 SchemaRewriteRequiresMigration,
2067
2068 SchemaTransitionBudgetExceeded {
2069 resource: SchemaTransitionBudgetResource,
2070 },
2071
2072 GeneratedFieldDefaultChangeRejected,
2073
2074 GeneratedFieldNullabilityChangeRejected,
2075}
2076
2077impl fmt::Display for SchemaDdlAdmissionError {
2078 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2079 f.write_str(COMPACT_QUERY_DIAGNOSTIC_MESSAGE)
2080 }
2081}
2082
2083impl std::error::Error for SchemaDdlAdmissionError {}
2084
2085impl fmt::Debug for ErrorDetail {
2086 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2087 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2088 }
2089}
2090
2091impl fmt::Debug for ExecutorErrorDetail {
2092 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2093 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2094 }
2095}
2096
2097impl fmt::Debug for StoreError {
2098 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2099 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2100 }
2101}
2102
2103impl fmt::Debug for QueryErrorDetail {
2104 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2105 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2106 }
2107}
2108
2109impl fmt::Debug for RecoveryErrorDetail {
2110 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2111 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2112 }
2113}
2114
2115impl fmt::Debug for SerializeErrorDetail {
2116 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2117 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2118 }
2119}
2120
2121impl fmt::Debug for RecoveryFormatMarkerError {
2122 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2123 fmt_compact_diagnostic(
2124 f,
2125 diagnostic_code::DiagnosticCode::RuntimeCorruption,
2126 Some(diagnostic_code::DiagnosticDetail::RuntimeKind {
2127 kind: diagnostic_code::RuntimeErrorKind::Corruption,
2128 }),
2129 )
2130 }
2131}
2132
2133impl fmt::Debug for SchemaDdlAdmissionError {
2134 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2135 fmt_compact_diagnostic(
2136 f,
2137 diagnostic_code::DiagnosticCode::SchemaDdlAdmission,
2138 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2139 reason: self.diagnostic_code(),
2140 }),
2141 )
2142 }
2143}
2144
2145fn fmt_compact_diagnostic(
2146 f: &mut fmt::Formatter<'_>,
2147 code: diagnostic_code::DiagnosticCode,
2148 detail: Option<diagnostic_code::DiagnosticDetail>,
2149) -> fmt::Result {
2150 write!(
2151 f,
2152 "{}",
2153 diagnostic_code::ErrorCode::from_parts(code, detail).raw()
2154 )
2155}
2156
2157impl ErrorDetail {
2158 #[must_use]
2160 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2161 match self {
2162 Self::Executor(error) => error.diagnostic_code(),
2163 Self::Store(error) => error.diagnostic_code(),
2164 Self::Query(error) => error.diagnostic_code(),
2165 Self::Recovery(error) => error.diagnostic_code(),
2166 Self::Serialize(error) => error.diagnostic_code(),
2167 }
2168 }
2169
2170 #[must_use]
2172 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2173 match self {
2174 Self::Executor(error) => error.diagnostic_detail(),
2175 Self::Store(error) => error.diagnostic_detail(),
2176 Self::Query(error) => error.diagnostic_detail(),
2177 Self::Recovery(error) => error.diagnostic_detail(),
2178 Self::Serialize(error) => error.diagnostic_detail(),
2179 }
2180 }
2181}
2182
2183impl ExecutorErrorDetail {
2184 #[must_use]
2186 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2187 match self {
2188 Self::MutationRequiredFieldMissing
2189 | Self::MutationDatabaseOwnedFieldExplicit
2190 | Self::MutationBatchEmpty
2191 | Self::MutationBatchTooManyItems
2192 | Self::MutationBatchStagedBytesExceeded
2193 | Self::MutationBatchResultBytesExceeded => {
2194 diagnostic_code::DiagnosticCode::RuntimeUnsupported
2195 }
2196 Self::MutationBatchEntityMismatch | Self::MutationBatchDuplicateKey => {
2197 diagnostic_code::DiagnosticCode::RuntimeConflict
2198 }
2199 Self::MutationManagedTimestampRegression => {
2200 diagnostic_code::DiagnosticCode::RuntimeInvariantViolation
2201 }
2202 Self::ConstraintViolation { diagnostic }
2203 | Self::ConstraintActivationWriteBlocked { diagnostic } => {
2204 diagnostic.error_code().diagnostic_code()
2205 }
2206 Self::AcceptedRowConstraintProgramCorrupt => {
2207 diagnostic_code::DiagnosticCode::RuntimeCorruption
2208 }
2209 }
2210 }
2211
2212 #[must_use]
2214 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2215 match self {
2216 Self::MutationRequiredFieldMissing => {
2217 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2218 boundary: diagnostic_code::RuntimeBoundaryCode::MutationRequiredFieldMissing,
2219 })
2220 }
2221 Self::MutationDatabaseOwnedFieldExplicit => {
2222 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2223 boundary:
2224 diagnostic_code::RuntimeBoundaryCode::MutationDatabaseOwnedFieldExplicit,
2225 })
2226 }
2227 Self::MutationBatchEmpty => Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2228 boundary: diagnostic_code::RuntimeBoundaryCode::MutationBatchEmpty,
2229 }),
2230 Self::MutationBatchTooManyItems => {
2231 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2232 boundary: diagnostic_code::RuntimeBoundaryCode::MutationBatchTooManyItems,
2233 })
2234 }
2235 Self::MutationBatchStagedBytesExceeded => {
2236 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2237 boundary:
2238 diagnostic_code::RuntimeBoundaryCode::MutationBatchStagedBytesExceeded,
2239 })
2240 }
2241 Self::MutationBatchResultBytesExceeded => {
2242 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2243 boundary:
2244 diagnostic_code::RuntimeBoundaryCode::MutationBatchResultBytesExceeded,
2245 })
2246 }
2247 Self::MutationBatchEntityMismatch => {
2248 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2249 boundary: diagnostic_code::RuntimeBoundaryCode::MutationBatchEntityMismatch,
2250 })
2251 }
2252 Self::MutationBatchDuplicateKey => {
2253 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2254 boundary: diagnostic_code::RuntimeBoundaryCode::MutationBatchDuplicateKey,
2255 })
2256 }
2257 Self::MutationManagedTimestampRegression => {
2258 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2259 boundary:
2260 diagnostic_code::RuntimeBoundaryCode::MutationManagedTimestampRegression,
2261 })
2262 }
2263 Self::ConstraintViolation { diagnostic }
2264 | Self::ConstraintActivationWriteBlocked { diagnostic } => {
2265 diagnostic.error_code().diagnostic_detail()
2266 }
2267 Self::AcceptedRowConstraintProgramCorrupt => {
2268 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2269 boundary:
2270 diagnostic_code::RuntimeBoundaryCode::AcceptedRowConstraintProgramCorrupt,
2271 })
2272 }
2273 }
2274 }
2275}
2276
2277impl RecoveryErrorDetail {
2278 #[must_use]
2280 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2281 match self {
2282 Self::UnsupportedFormatVersion { .. } => {
2283 diagnostic_code::DiagnosticCode::RuntimeIncompatiblePersistedFormat
2284 }
2285 Self::MalformedFormatMarker { .. } => {
2286 diagnostic_code::DiagnosticCode::RuntimeCorruption
2287 }
2288 }
2289 }
2290
2291 #[must_use]
2293 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2294 let kind = match self {
2295 Self::UnsupportedFormatVersion { .. } => {
2296 diagnostic_code::RuntimeErrorKind::IncompatiblePersistedFormat
2297 }
2298 Self::MalformedFormatMarker { .. } => diagnostic_code::RuntimeErrorKind::Corruption,
2299 };
2300
2301 Some(diagnostic_code::DiagnosticDetail::RuntimeKind { kind })
2302 }
2303}
2304
2305impl SerializeErrorDetail {
2306 #[must_use]
2308 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2309 match self {
2310 Self::PersistedRowLayoutOutsideAcceptedWindow | Self::PersistedRowSlotCountMismatch => {
2311 diagnostic_code::DiagnosticCode::RuntimeCorruption
2312 }
2313 }
2314 }
2315
2316 #[must_use]
2318 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2319 let boundary = match self {
2320 Self::PersistedRowLayoutOutsideAcceptedWindow => {
2321 diagnostic_code::RuntimeBoundaryCode::PersistedRowLayoutOutsideAcceptedWindow
2322 }
2323 Self::PersistedRowSlotCountMismatch => {
2324 diagnostic_code::RuntimeBoundaryCode::PersistedRowSlotCountMismatch
2325 }
2326 };
2327
2328 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary { boundary })
2329 }
2330}
2331
2332impl StoreError {
2333 #[must_use]
2335 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2336 match self {
2337 Self::NotFound => diagnostic_code::DiagnosticCode::StoreNotFound,
2338 Self::Corrupt => diagnostic_code::DiagnosticCode::StoreCorruption,
2339 Self::InvariantViolation => diagnostic_code::DiagnosticCode::StoreInvariantViolation,
2340 Self::SchemaDdlPublicationRaceLost
2341 | Self::SchemaDdlRewriteRequiresMigration
2342 | Self::SchemaRowLayoutVersionExhausted
2343 | Self::SchemaTransitionBudgetExceeded { .. } => {
2344 diagnostic_code::DiagnosticCode::SchemaDdlAdmission
2345 }
2346 Self::JournalMutationRevisionExhausted | Self::SchemaGeneratedFieldAfterDdlField => {
2347 diagnostic_code::DiagnosticCode::RuntimeUnsupported
2348 }
2349 Self::SchemaGeneratedConstraintActivationStale => {
2350 diagnostic_code::DiagnosticCode::RuntimeConflict
2351 }
2352 }
2353 }
2354
2355 #[must_use]
2357 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2358 match self {
2359 Self::SchemaDdlPublicationRaceLost => {
2360 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2361 reason: diagnostic_code::SchemaDdlAdmissionCode::PublicationRaceLost,
2362 })
2363 }
2364 Self::SchemaDdlRewriteRequiresMigration => {
2365 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2366 reason: diagnostic_code::SchemaDdlAdmissionCode::SchemaRewriteRequiresMigration,
2367 })
2368 }
2369 Self::SchemaRowLayoutVersionExhausted => {
2370 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2371 reason: diagnostic_code::SchemaDdlAdmissionCode::RowLayoutVersionExhausted,
2372 })
2373 }
2374 Self::JournalMutationRevisionExhausted => {
2375 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2376 boundary:
2377 diagnostic_code::RuntimeBoundaryCode::JournalMutationRevisionExhausted,
2378 })
2379 }
2380 Self::SchemaTransitionBudgetExceeded { .. } => {
2381 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2382 reason: diagnostic_code::SchemaDdlAdmissionCode::SchemaTransitionBudgetExceeded,
2383 })
2384 }
2385 Self::SchemaGeneratedFieldAfterDdlField => {
2386 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2387 boundary: diagnostic_code::RuntimeBoundaryCode::GeneratedFieldAfterDdlField,
2388 })
2389 }
2390 Self::SchemaGeneratedConstraintActivationStale => {
2391 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2392 boundary:
2393 diagnostic_code::RuntimeBoundaryCode::GeneratedConstraintActivationStale,
2394 })
2395 }
2396 Self::NotFound | Self::Corrupt | Self::InvariantViolation => None,
2397 }
2398 }
2399}
2400
2401impl QueryErrorDetail {
2402 #[must_use]
2404 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2405 match self {
2406 Self::NumericOverflow => diagnostic_code::DiagnosticCode::QueryNumericOverflow,
2407 Self::NumericNotRepresentable => {
2408 diagnostic_code::DiagnosticCode::QueryNumericNotRepresentable
2409 }
2410 Self::UnsupportedSqlFeature { .. } => {
2411 diagnostic_code::DiagnosticCode::QueryUnsupportedSqlFeature
2412 }
2413 Self::SqlLowering { .. } => diagnostic_code::DiagnosticCode::QueryUnsupportedSqlFeature,
2414 Self::UnsupportedProjection { .. } => {
2415 diagnostic_code::DiagnosticCode::QueryUnsupportedProjection
2416 }
2417 Self::UnknownAggregateTargetField => {
2418 diagnostic_code::DiagnosticCode::QueryUnknownAggregateTargetField
2419 }
2420 Self::ResultShapeMismatch { .. } => {
2421 diagnostic_code::DiagnosticCode::QueryResultShapeMismatch
2422 }
2423 Self::QueryReadAdmission { .. } => diagnostic_code::DiagnosticCode::QueryReadAdmission,
2424 Self::SqlSurfaceMismatch { .. } => {
2425 diagnostic_code::DiagnosticCode::QuerySqlSurfaceMismatch
2426 }
2427 Self::SqlWriteBoundary { .. } => diagnostic_code::DiagnosticCode::QuerySqlWriteBoundary,
2428 Self::SchemaDdlAdmission { .. } => diagnostic_code::DiagnosticCode::SchemaDdlAdmission,
2429 Self::StaleSchemaRevision => diagnostic_code::DiagnosticCode::RuntimeConflict,
2430 }
2431 }
2432
2433 #[must_use]
2435 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2436 match self {
2437 Self::UnsupportedSqlFeature { feature } => {
2438 Some(diagnostic_code::DiagnosticDetail::UnsupportedSqlFeature { feature: *feature })
2439 }
2440 Self::SqlLowering { reason } => {
2441 Some(diagnostic_code::DiagnosticDetail::SqlLowering { reason: *reason })
2442 }
2443 Self::UnsupportedProjection { reason } => {
2444 Some(diagnostic_code::DiagnosticDetail::QueryProjection { reason: *reason })
2445 }
2446 Self::ResultShapeMismatch { reason } => {
2447 Some(diagnostic_code::DiagnosticDetail::QueryResultShape { reason: *reason })
2448 }
2449 Self::QueryReadAdmission { reason } => {
2450 Some(diagnostic_code::DiagnosticDetail::QueryReadAdmission { reason: *reason })
2451 }
2452 Self::SqlSurfaceMismatch { mismatch } => {
2453 Some(diagnostic_code::DiagnosticDetail::SqlSurfaceMismatch {
2454 mismatch: *mismatch,
2455 })
2456 }
2457 Self::SqlWriteBoundary { boundary } => {
2458 Some(diagnostic_code::DiagnosticDetail::SqlWriteBoundary {
2459 boundary: *boundary,
2460 })
2461 }
2462 Self::SchemaDdlAdmission { error } => {
2463 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2464 reason: error.diagnostic_code(),
2465 })
2466 }
2467 Self::NumericOverflow
2468 | Self::NumericNotRepresentable
2469 | Self::UnknownAggregateTargetField
2470 | Self::StaleSchemaRevision => None,
2471 }
2472 }
2473}
2474
2475impl SchemaDdlAdmissionError {
2476 #[must_use]
2478 pub const fn diagnostic_code(&self) -> diagnostic_code::SchemaDdlAdmissionCode {
2479 match self {
2480 Self::MissingExpectedSchemaVersion => {
2481 diagnostic_code::SchemaDdlAdmissionCode::MissingExpectedSchemaVersion
2482 }
2483 Self::MissingNextSchemaVersion => {
2484 diagnostic_code::SchemaDdlAdmissionCode::MissingNextSchemaVersion
2485 }
2486 Self::StaleExpectedSchemaVersion => {
2487 diagnostic_code::SchemaDdlAdmissionCode::StaleExpectedSchemaVersion
2488 }
2489 Self::InvalidExpectedSchemaVersion => {
2490 diagnostic_code::SchemaDdlAdmissionCode::InvalidExpectedSchemaVersion
2491 }
2492 Self::InvalidNextSchemaVersion => {
2493 diagnostic_code::SchemaDdlAdmissionCode::InvalidNextSchemaVersion
2494 }
2495 Self::AcceptedSchemaChangeWithoutVersionBump => {
2496 diagnostic_code::SchemaDdlAdmissionCode::AcceptedSchemaChangeWithoutVersionBump
2497 }
2498 Self::EmptyVersionBump => diagnostic_code::SchemaDdlAdmissionCode::EmptyVersionBump,
2499 Self::VersionGap => diagnostic_code::SchemaDdlAdmissionCode::VersionGap,
2500 Self::VersionRollback => diagnostic_code::SchemaDdlAdmissionCode::VersionRollback,
2501 Self::FingerprintMethodMismatch => {
2502 diagnostic_code::SchemaDdlAdmissionCode::FingerprintMethodMismatch
2503 }
2504 Self::UnsupportedTransitionClass => {
2505 diagnostic_code::SchemaDdlAdmissionCode::UnsupportedTransitionClass
2506 }
2507 Self::PhysicalRunnerMissing => {
2508 diagnostic_code::SchemaDdlAdmissionCode::PhysicalRunnerMissing
2509 }
2510 Self::ValidationFailed => diagnostic_code::SchemaDdlAdmissionCode::ValidationFailed,
2511 Self::PublicationRaceLost => {
2512 diagnostic_code::SchemaDdlAdmissionCode::PublicationRaceLost
2513 }
2514 Self::InvalidAddColumnDefault => {
2515 diagnostic_code::SchemaDdlAdmissionCode::InvalidAddColumnDefault
2516 }
2517 Self::InvalidAlterColumnDefault => {
2518 diagnostic_code::SchemaDdlAdmissionCode::InvalidAlterColumnDefault
2519 }
2520 Self::GeneratedIndexDropRejected => {
2521 diagnostic_code::SchemaDdlAdmissionCode::GeneratedIndexDropRejected
2522 }
2523 Self::SchemaRewriteRequiresMigration => {
2524 diagnostic_code::SchemaDdlAdmissionCode::SchemaRewriteRequiresMigration
2525 }
2526 Self::SchemaTransitionBudgetExceeded { .. } => {
2527 diagnostic_code::SchemaDdlAdmissionCode::SchemaTransitionBudgetExceeded
2528 }
2529 Self::GeneratedFieldDefaultChangeRejected => {
2530 diagnostic_code::SchemaDdlAdmissionCode::GeneratedFieldDefaultChangeRejected
2531 }
2532 Self::GeneratedFieldNullabilityChangeRejected => {
2533 diagnostic_code::SchemaDdlAdmissionCode::GeneratedFieldNullabilityChangeRejected
2534 }
2535 Self::RowLayoutVersionExhausted => {
2536 diagnostic_code::SchemaDdlAdmissionCode::RowLayoutVersionExhausted
2537 }
2538 }
2539 }
2540}
2541
2542#[repr(u8)]
2549#[derive(Clone, Copy, Eq, PartialEq)]
2550pub enum ErrorClass {
2551 Corruption,
2552 IncompatiblePersistedFormat,
2553 NotFound,
2554 Internal,
2555 Conflict,
2556 Unsupported,
2557 InvariantViolation,
2558}
2559
2560impl ErrorClass {
2561 #[must_use]
2563 pub const fn diagnostic_code(self, origin: ErrorOrigin) -> diagnostic_code::DiagnosticCode {
2564 match self {
2565 Self::Corruption if matches!(origin, ErrorOrigin::Store) => {
2566 diagnostic_code::DiagnosticCode::StoreCorruption
2567 }
2568 Self::Corruption => diagnostic_code::DiagnosticCode::RuntimeCorruption,
2569 Self::IncompatiblePersistedFormat => {
2570 diagnostic_code::DiagnosticCode::RuntimeIncompatiblePersistedFormat
2571 }
2572 Self::NotFound if matches!(origin, ErrorOrigin::Store) => {
2573 diagnostic_code::DiagnosticCode::StoreNotFound
2574 }
2575 Self::NotFound => diagnostic_code::DiagnosticCode::RuntimeNotFound,
2576 Self::Internal => diagnostic_code::DiagnosticCode::RuntimeInternal,
2577 Self::Conflict => diagnostic_code::DiagnosticCode::RuntimeConflict,
2578 Self::Unsupported if matches!(origin, ErrorOrigin::Cursor) => {
2579 diagnostic_code::DiagnosticCode::QueryInvalidContinuationCursor
2580 }
2581 Self::Unsupported => diagnostic_code::DiagnosticCode::RuntimeUnsupported,
2582 Self::InvariantViolation if matches!(origin, ErrorOrigin::Store) => {
2583 diagnostic_code::DiagnosticCode::StoreInvariantViolation
2584 }
2585 Self::InvariantViolation => diagnostic_code::DiagnosticCode::RuntimeInvariantViolation,
2586 }
2587 }
2588}
2589
2590impl fmt::Debug for ErrorClass {
2591 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2592 write!(f, "{}", *self as u8)
2593 }
2594}
2595
2596#[repr(u8)]
2603#[derive(Clone, Copy, Eq, PartialEq)]
2604pub enum ErrorOrigin {
2605 Serialize,
2606 Store,
2607 Index,
2608 Identity,
2609 Query,
2610 Planner,
2611 Cursor,
2612 Recovery,
2613 Response,
2614 Executor,
2615 Interface,
2616}
2617
2618impl ErrorOrigin {
2619 #[must_use]
2621 pub const fn diagnostic_origin(self) -> diagnostic_code::ErrorOrigin {
2622 match self {
2623 Self::Serialize => diagnostic_code::ErrorOrigin::Serialize,
2624 Self::Store => diagnostic_code::ErrorOrigin::Store,
2625 Self::Index => diagnostic_code::ErrorOrigin::Index,
2626 Self::Identity => diagnostic_code::ErrorOrigin::Identity,
2627 Self::Query => diagnostic_code::ErrorOrigin::Query,
2628 Self::Planner => diagnostic_code::ErrorOrigin::Planner,
2629 Self::Cursor => diagnostic_code::ErrorOrigin::Cursor,
2630 Self::Recovery => diagnostic_code::ErrorOrigin::Recovery,
2631 Self::Response => diagnostic_code::ErrorOrigin::Response,
2632 Self::Executor => diagnostic_code::ErrorOrigin::Executor,
2633 Self::Interface => diagnostic_code::ErrorOrigin::Interface,
2634 }
2635 }
2636}
2637
2638impl fmt::Debug for ErrorOrigin {
2639 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2640 write!(f, "{}", *self as u8)
2641 }
2642}