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_key_item_field_missing_on_entity_model(_field: &str) -> Self {
277 Self::index_invariant()
278 }
279
280 pub(crate) fn index_key_item_field_missing_on_lookup_row(_field: &str) -> Self {
282 Self::index_invariant()
283 }
284
285 pub(crate) fn index_expression_source_type_mismatch(
287 _index_name: &str,
288 _expression: impl Sized,
289 _expected: impl Sized,
290 _source_label: &str,
291 ) -> Self {
292 Self::index_invariant()
293 }
294
295 #[cold]
298 #[inline(never)]
299 pub(crate) fn planner_executor_invariant() -> Self {
300 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Planner)
301 }
302
303 #[cold]
306 #[inline(never)]
307 pub(crate) fn query_executor_invariant() -> Self {
308 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Query)
309 }
310
311 #[cold]
314 #[inline(never)]
315 pub(crate) fn cursor_executor_invariant() -> Self {
316 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Cursor)
317 }
318
319 #[cold]
321 #[inline(never)]
322 pub(crate) fn executor_invariant() -> Self {
323 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Executor)
324 }
325
326 #[cold]
328 #[inline(never)]
329 pub(crate) fn executor_conflict() -> Self {
330 Self::new(ErrorClass::Conflict, ErrorOrigin::Executor)
331 }
332
333 #[cold]
335 #[inline(never)]
336 pub(crate) fn executor_internal() -> Self {
337 Self::new(ErrorClass::Internal, ErrorOrigin::Executor)
338 }
339
340 #[cold]
342 #[inline(never)]
343 pub(crate) fn executor_unsupported() -> Self {
344 Self::new(ErrorClass::Unsupported, ErrorOrigin::Executor)
345 }
346
347 pub(crate) fn mutation_entity_primary_key_missing(
349 _entity_path: &str,
350 _field_name: &str,
351 ) -> Self {
352 Self::executor_invariant()
353 }
354
355 pub(crate) fn mutation_entity_primary_key_invalid_value(
357 _entity_path: &str,
358 _field_name: &str,
359 _value: &crate::value::Value,
360 ) -> Self {
361 Self::executor_invariant()
362 }
363
364 pub(crate) fn mutation_entity_primary_key_type_mismatch(
366 _entity_path: &str,
367 _field_name: &str,
368 _value: &crate::value::Value,
369 ) -> Self {
370 Self::executor_invariant()
371 }
372
373 pub(crate) fn mutation_entity_primary_key_mismatch(
375 _entity_path: &str,
376 _field_name: &str,
377 _field_value: &crate::value::Value,
378 _identity_key: &crate::value::Value,
379 ) -> Self {
380 Self::executor_invariant()
381 }
382
383 pub(crate) fn mutation_entity_field_missing(
385 _entity_path: &str,
386 _field_name: &str,
387 _indexed: bool,
388 ) -> Self {
389 Self::executor_invariant()
390 }
391
392 pub(crate) fn mutation_structural_patch_required_field_missing(
394 entity_path: &str,
395 field_name: &str,
396 ) -> Self {
397 Self::mutation_required_field_missing(entity_path, field_name)
398 }
399
400 pub(crate) fn mutation_entity_field_type_mismatch(
402 _entity_path: &str,
403 _field_name: &str,
404 _value: &crate::value::Value,
405 ) -> Self {
406 Self::executor_invariant()
407 }
408
409 pub(crate) fn mutation_database_owned_field_explicit(
411 _entity_path: &str,
412 _field_name: &str,
413 ) -> Self {
414 Self::executor_unsupported()
415 }
416
417 pub(crate) fn mutation_sanitizer_protected_field_changed(
419 _entity_path: &str,
420 _field_name: &str,
421 ) -> Self {
422 Self::executor_unsupported()
423 }
424
425 #[must_use]
427 pub fn mutation_required_field_missing(_entity_path: &str, _field_names: &str) -> Self {
428 Self {
429 class: ErrorClass::Unsupported,
430 origin: ErrorOrigin::Executor,
431 detail: Some(ErrorDetail::Executor(
432 ExecutorErrorDetail::MutationRequiredFieldMissing,
433 )),
434 }
435 }
436
437 pub(crate) fn mutation_constraint_violation(diagnostic: ConstraintDiagnostic) -> Self {
439 Self {
440 class: ErrorClass::InvariantViolation,
441 origin: ErrorOrigin::Executor,
442 detail: Some(ErrorDetail::Executor(
443 ExecutorErrorDetail::ConstraintViolation {
444 diagnostic: Box::new(diagnostic),
445 },
446 )),
447 }
448 }
449
450 pub(crate) fn accepted_row_constraint_program_corrupt() -> Self {
452 Self {
453 class: ErrorClass::Corruption,
454 origin: ErrorOrigin::Executor,
455 detail: Some(ErrorDetail::Executor(
456 ExecutorErrorDetail::AcceptedRowConstraintProgramCorrupt,
457 )),
458 }
459 }
460
461 pub(crate) fn mutation_constraint_activation_write_blocked(
463 diagnostic: ConstraintDiagnostic,
464 ) -> Self {
465 Self {
466 class: ErrorClass::Conflict,
467 origin: ErrorOrigin::Executor,
468 detail: Some(ErrorDetail::Executor(
469 ExecutorErrorDetail::ConstraintActivationWriteBlocked {
470 diagnostic: Box::new(diagnostic),
471 },
472 )),
473 }
474 }
475
476 pub(crate) fn mutation_structural_after_image_invalid(
481 _entity_path: &str,
482 _data_key: impl Sized,
483 _detail: impl Sized,
484 ) -> Self {
485 Self::executor_invariant()
486 }
487
488 pub(crate) fn mutation_structural_field_unknown(_entity_path: &str, _field_name: &str) -> Self {
490 Self::executor_invariant()
491 }
492
493 pub(crate) fn mutation_decimal_scale_mismatch(
495 _entity_path: &str,
496 _field_name: &str,
497 _expected_scale: impl Sized,
498 _actual_scale: impl Sized,
499 ) -> Self {
500 Self::executor_unsupported()
501 }
502
503 pub(crate) fn mutation_text_max_len_exceeded(
505 _entity_path: &str,
506 _field_name: &str,
507 _max_len: impl Sized,
508 _actual_len: impl Sized,
509 ) -> Self {
510 Self::executor_unsupported()
511 }
512
513 pub(crate) fn mutation_set_field_list_required(_entity_path: &str, _field_name: &str) -> Self {
515 Self::executor_invariant()
516 }
517
518 pub(crate) fn mutation_set_field_not_canonical(_entity_path: &str, _field_name: &str) -> Self {
520 Self::executor_invariant()
521 }
522
523 pub(crate) fn mutation_map_field_map_required(_entity_path: &str, _field_name: &str) -> Self {
525 Self::executor_invariant()
526 }
527
528 pub(crate) fn mutation_map_field_entries_invalid(
530 _entity_path: &str,
531 _field_name: &str,
532 _detail: impl Sized,
533 ) -> Self {
534 Self::executor_invariant()
535 }
536
537 pub(crate) fn mutation_map_field_entries_not_canonical(
539 _entity_path: &str,
540 _field_name: &str,
541 ) -> Self {
542 Self::executor_invariant()
543 }
544
545 pub(crate) fn scalar_page_cursor_boundary_order_required() -> Self {
547 Self::query_executor_invariant()
548 }
549
550 pub(crate) fn scalar_page_cursor_boundary_after_ordering_required() -> Self {
552 Self::query_executor_invariant()
553 }
554
555 pub(crate) fn scalar_page_pagination_after_ordering_required() -> Self {
557 Self::query_executor_invariant()
558 }
559
560 pub(crate) fn load_executor_load_plan_required() -> Self {
562 Self::query_executor_invariant()
563 }
564
565 pub(crate) fn delete_executor_grouped_unsupported() -> Self {
567 Self::executor_unsupported()
568 }
569
570 pub(crate) fn delete_executor_delete_plan_required() -> Self {
572 Self::query_executor_invariant()
573 }
574
575 pub(crate) fn aggregate_fold_mode_terminal_contract_required() -> Self {
577 Self::query_executor_invariant()
578 }
579
580 pub(crate) fn fast_stream_route_kind_request_match_required() -> Self {
582 Self::query_executor_invariant()
583 }
584
585 pub(crate) fn secondary_index_prefix_spec_required() -> Self {
587 Self::query_executor_invariant()
588 }
589
590 pub(crate) fn index_range_limit_spec_required() -> Self {
592 Self::query_executor_invariant()
593 }
594
595 pub(crate) fn mutation_atomic_save_duplicate_key(_entity_path: &str, _key: impl Sized) -> Self {
597 Self::executor_conflict()
598 }
599
600 pub(crate) fn mutation_index_store_generation_changed(
602 _expected_generation: u64,
603 _observed_generation: u64,
604 ) -> Self {
605 Self::executor_invariant()
606 }
607
608 #[cold]
610 #[inline(never)]
611 pub(crate) fn planner_invariant() -> Self {
612 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Planner)
613 }
614
615 pub(crate) fn query_invalid_logical_plan() -> Self {
617 Self::planner_invariant()
618 }
619
620 pub(crate) fn store_invariant() -> Self {
622 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Store)
623 }
624
625 pub(crate) fn duplicate_runtime_hooks_for_entity_tag(
627 _entity_tag: crate::types::EntityTag,
628 ) -> Self {
629 Self::store_invariant()
630 }
631
632 pub(crate) fn duplicate_runtime_hooks_for_entity_path(_entity_path: &str) -> Self {
634 Self::store_invariant()
635 }
636
637 #[cold]
639 #[inline(never)]
640 pub(crate) fn store_internal() -> Self {
641 Self::new(ErrorClass::Internal, ErrorOrigin::Store)
642 }
643
644 pub(crate) fn commit_memory_id_unconfigured() -> Self {
646 Self::store_internal()
647 }
648
649 pub(crate) fn commit_memory_id_mismatch(_cached_id: u8, _configured_id: u8) -> Self {
651 Self::store_internal()
652 }
653
654 pub(crate) fn commit_memory_stable_key_mismatch(
656 _cached_key: &str,
657 _configured_key: &str,
658 ) -> Self {
659 Self::store_internal()
660 }
661
662 pub(crate) fn recovery_unsupported_database_format(found: Option<u16>, required: u16) -> Self {
664 Self {
665 class: ErrorClass::IncompatiblePersistedFormat,
666 origin: ErrorOrigin::Recovery,
667 detail: Some(ErrorDetail::Recovery(
668 RecoveryErrorDetail::UnsupportedFormatVersion { found, required },
669 )),
670 }
671 }
672
673 pub(crate) fn recovery_malformed_database_format_marker(
675 reason: RecoveryFormatMarkerError,
676 ) -> Self {
677 Self {
678 class: ErrorClass::Corruption,
679 origin: ErrorOrigin::Recovery,
680 detail: Some(ErrorDetail::Recovery(
681 RecoveryErrorDetail::MalformedFormatMarker { reason },
682 )),
683 }
684 }
685
686 pub(crate) fn recovery_database_format_control_unavailable() -> Self {
688 Self::new(ErrorClass::Internal, ErrorOrigin::Recovery)
689 }
690
691 pub(crate) fn commit_control_memory_growth_failed() -> Self {
693 Self::store_internal()
694 }
695
696 #[cfg(not(test))]
698 pub(crate) fn database_format_memory_registration_failed(_err: impl Sized) -> Self {
699 Self::store_internal()
700 }
701
702 pub(crate) fn delete_rollback_row_required() -> Self {
704 Self::store_internal()
705 }
706
707 pub(crate) fn recovery_integrity_validation_failed(
709 _missing_index_entries: u64,
710 _divergent_index_entries: u64,
711 _orphan_index_references: u64,
712 ) -> Self {
713 Self::store_corruption()
714 }
715
716 #[cold]
718 #[inline(never)]
719 pub(crate) fn index_internal() -> Self {
720 Self::new(ErrorClass::Internal, ErrorOrigin::Index)
721 }
722
723 pub(crate) fn structural_index_removal_entity_key_required() -> Self {
725 Self::index_internal()
726 }
727
728 pub(crate) fn structural_index_insertion_entity_key_required() -> Self {
730 Self::index_internal()
731 }
732
733 pub(crate) fn index_commit_op_old_entity_key_required() -> Self {
735 Self::index_internal()
736 }
737
738 pub(crate) fn index_commit_op_new_entity_key_required() -> Self {
740 Self::index_internal()
741 }
742
743 #[cfg(test)]
745 pub(crate) fn query_internal() -> Self {
746 Self::new(ErrorClass::Internal, ErrorOrigin::Query)
747 }
748
749 #[cold]
751 #[inline(never)]
752 pub(crate) fn query_unsupported() -> Self {
753 Self::new(ErrorClass::Unsupported, ErrorOrigin::Query)
754 }
755
756 #[cold]
759 #[inline(never)]
760 pub(crate) fn query_stale_accepted_schema_revision(
761 _expected_revision: u64,
762 _current_revision: Option<u64>,
763 ) -> Self {
764 Self {
765 class: ErrorClass::Conflict,
766 origin: ErrorOrigin::Query,
767 detail: Some(ErrorDetail::Query(QueryErrorDetail::StaleSchemaRevision)),
768 }
769 }
770
771 #[cold]
773 #[inline(never)]
774 #[cfg(feature = "sql")]
775 pub(crate) fn query_schema_ddl_admission(error: SchemaDdlAdmissionError) -> Self {
776 Self {
777 class: ErrorClass::Unsupported,
778 origin: ErrorOrigin::Query,
779 detail: Some(ErrorDetail::Query(QueryErrorDetail::SchemaDdlAdmission {
780 error,
781 })),
782 }
783 }
784
785 #[cold]
787 #[inline(never)]
788 pub(crate) fn query_numeric_overflow() -> Self {
789 Self {
790 class: ErrorClass::Unsupported,
791 origin: ErrorOrigin::Query,
792 detail: Some(ErrorDetail::Query(QueryErrorDetail::NumericOverflow)),
793 }
794 }
795
796 #[cold]
799 #[inline(never)]
800 pub(crate) fn query_numeric_not_representable() -> Self {
801 Self {
802 class: ErrorClass::Unsupported,
803 origin: ErrorOrigin::Query,
804 detail: Some(ErrorDetail::Query(
805 QueryErrorDetail::NumericNotRepresentable,
806 )),
807 }
808 }
809
810 #[cold]
812 #[inline(never)]
813 pub(crate) fn serialize_internal() -> Self {
814 Self::new(ErrorClass::Internal, ErrorOrigin::Serialize)
815 }
816
817 pub(crate) fn persisted_row_encode_failed(_detail: impl Sized) -> Self {
819 Self::persisted_row_encode_internal()
820 }
821
822 pub(crate) fn persisted_row_encode_internal() -> Self {
824 Self::serialize_internal()
825 }
826
827 pub(crate) fn persisted_row_field_encode_failed(field_name: &str, _detail: impl Sized) -> Self {
829 Self::persisted_row_field_encode_internal(field_name)
830 }
831
832 pub(crate) fn persisted_row_field_encode_internal(_field_name: &str) -> Self {
834 Self::persisted_row_encode_internal()
835 }
836
837 pub(crate) fn bytes_field_value_encode_failed(_detail: impl Sized) -> Self {
839 Self::serialize_internal()
840 }
841
842 #[cold]
844 #[inline(never)]
845 pub(crate) fn store_corruption() -> Self {
846 Self::new(ErrorClass::Corruption, ErrorOrigin::Store)
847 }
848
849 pub(crate) fn commit_corruption() -> Self {
851 Self::store_corruption()
852 }
853
854 pub(crate) fn commit_component_corruption() -> Self {
856 Self::commit_corruption()
857 }
858
859 pub(crate) fn commit_id_generation_failed() -> Self {
861 Self::store_internal()
862 }
863
864 pub(crate) fn commit_marker_payload_exceeds_u32_length_limit() -> Self {
866 Self::store_unsupported()
867 }
868
869 pub(crate) fn commit_component_length_invalid() -> Self {
871 Self::commit_corruption()
872 }
873
874 pub(crate) fn commit_marker_exceeds_max_size() -> Self {
876 Self::commit_corruption()
877 }
878
879 pub(crate) fn commit_control_slot_exceeds_max_size() -> Self {
881 Self::store_unsupported()
882 }
883
884 pub(crate) fn commit_control_slot_marker_bytes_exceed_u32_length_limit() -> Self {
886 Self::store_unsupported()
887 }
888
889 pub(crate) fn startup_index_rebuild_invalid_data_key() -> Self {
891 Self::store_corruption()
892 }
893
894 #[cold]
896 #[inline(never)]
897 pub(crate) fn index_corruption() -> Self {
898 Self::new(ErrorClass::Corruption, ErrorOrigin::Index)
899 }
900
901 pub(crate) fn index_unique_validation_corruption() -> Self {
903 Self::index_plan_index_corruption()
904 }
905
906 pub(crate) fn structural_index_entry_corruption() -> Self {
908 Self::index_plan_index_corruption()
909 }
910
911 pub(crate) fn index_unique_validation_entity_key_required() -> Self {
913 Self::index_invariant()
914 }
915
916 pub(crate) fn index_unique_validation_row_deserialize_failed() -> Self {
918 Self::index_plan_serialize_corruption()
919 }
920
921 pub(crate) fn index_unique_validation_primary_key_decode_failed() -> Self {
923 Self::index_plan_serialize_corruption()
924 }
925
926 pub(crate) fn index_unique_validation_key_rebuild_failed() -> Self {
928 Self::index_plan_serialize_corruption()
929 }
930
931 pub(crate) fn index_unique_validation_row_required() -> Self {
933 Self::index_plan_store_corruption()
934 }
935
936 pub(crate) fn index_only_predicate_component_required() -> Self {
938 Self::index_invariant()
939 }
940
941 pub(crate) fn index_scan_continuation_anchor_within_envelope_required() -> Self {
943 Self::index_invariant()
944 }
945
946 pub(crate) fn index_scan_continuation_advancement_required() -> Self {
948 Self::index_invariant()
949 }
950
951 pub(crate) fn index_scan_key_corrupted_during(
953 _context: &'static str,
954 _err: impl Sized,
955 ) -> Self {
956 Self::index_corruption()
957 }
958
959 pub(crate) fn index_projection_component_required(
961 _index_name: &str,
962 _component_index: usize,
963 ) -> Self {
964 Self::index_invariant()
965 }
966
967 pub(crate) fn index_entry_decode_failed() -> Self {
969 Self::index_corruption()
970 }
971
972 pub(crate) fn serialize_corruption() -> Self {
974 Self::new(ErrorClass::Corruption, ErrorOrigin::Serialize)
975 }
976
977 pub(crate) fn persisted_row_decode_failed(_detail: impl Sized) -> Self {
979 Self::persisted_row_decode_corruption()
980 }
981
982 pub(crate) fn persisted_row_decode_corruption() -> Self {
984 Self::serialize_corruption()
985 }
986
987 pub(crate) fn persisted_row_layout_outside_accepted_window() -> Self {
989 Self {
990 class: ErrorClass::Corruption,
991 origin: ErrorOrigin::Serialize,
992 detail: Some(ErrorDetail::Serialize(
993 SerializeErrorDetail::PersistedRowLayoutOutsideAcceptedWindow,
994 )),
995 }
996 }
997
998 pub(crate) fn persisted_row_slot_count_mismatch() -> Self {
1000 Self {
1001 class: ErrorClass::Corruption,
1002 origin: ErrorOrigin::Serialize,
1003 detail: Some(ErrorDetail::Serialize(
1004 SerializeErrorDetail::PersistedRowSlotCountMismatch,
1005 )),
1006 }
1007 }
1008
1009 pub(crate) fn persisted_row_field_decode_failed(field_name: &str, _detail: impl Sized) -> Self {
1011 Self::persisted_row_field_decode_corruption(field_name)
1012 }
1013
1014 pub(crate) fn persisted_row_field_decode_corruption(_field_name: &str) -> Self {
1016 Self::persisted_row_decode_corruption()
1017 }
1018
1019 pub(crate) fn persisted_row_field_kind_decode_failed(
1021 field_name: &str,
1022 _field_kind: impl fmt::Debug,
1023 _detail: impl Sized,
1024 ) -> Self {
1025 Self::persisted_row_field_decode_corruption(field_name)
1026 }
1027
1028 pub(crate) fn persisted_row_field_payload_exact_len_required(field_name: &str) -> Self {
1030 Self::persisted_row_field_decode_corruption(field_name)
1031 }
1032
1033 pub(crate) fn persisted_row_field_payload_must_be_empty(field_name: &str) -> Self {
1035 Self::persisted_row_field_decode_corruption(field_name)
1036 }
1037
1038 pub(crate) fn persisted_row_field_payload_invalid_byte(field_name: &str) -> Self {
1040 Self::persisted_row_field_decode_corruption(field_name)
1041 }
1042
1043 pub(crate) fn persisted_row_field_payload_non_finite(field_name: &str) -> Self {
1045 Self::persisted_row_field_decode_corruption(field_name)
1046 }
1047
1048 pub(crate) fn persisted_row_field_payload_out_of_range(field_name: &str) -> Self {
1050 Self::persisted_row_field_decode_corruption(field_name)
1051 }
1052
1053 pub(crate) fn persisted_row_field_text_payload_invalid_utf8(field_name: &str) -> Self {
1055 Self::persisted_row_field_decode_corruption(field_name)
1056 }
1057
1058 pub(crate) fn persisted_row_slot_lookup_out_of_bounds(_model_path: &str, _slot: usize) -> Self {
1060 Self::index_invariant()
1061 }
1062
1063 pub(crate) fn persisted_row_slot_cache_lookup_out_of_bounds(
1065 _model_path: &str,
1066 _slot: usize,
1067 ) -> Self {
1068 Self::index_invariant()
1069 }
1070
1071 pub(crate) fn persisted_row_primary_key_not_primary_key_encodable(
1073 _data_key: impl fmt::Debug,
1074 _detail: impl Sized,
1075 ) -> Self {
1076 Self::persisted_row_decode_corruption()
1077 }
1078
1079 pub(crate) fn persisted_row_primary_key_slot_missing(_data_key: impl fmt::Debug) -> Self {
1081 Self::persisted_row_decode_corruption()
1082 }
1083
1084 pub(crate) fn persisted_row_key_mismatch() -> Self {
1086 Self::store_corruption()
1087 }
1088
1089 pub(crate) fn persisted_row_declared_field_missing(field_name: &str) -> Self {
1091 Self::persisted_row_field_decode_corruption(field_name)
1092 }
1093
1094 pub(crate) fn data_key_entity_mismatch() -> Self {
1096 Self::store_corruption()
1097 }
1098
1099 pub(crate) fn reverse_index_ordinal_overflow(
1101 _source_path: &str,
1102 _field_name: &str,
1103 _target_path: &str,
1104 _detail: impl Sized,
1105 ) -> Self {
1106 Self::index_internal()
1107 }
1108
1109 pub(crate) fn reverse_index_entry_corrupted(
1111 _source_path: &str,
1112 _field_name: &str,
1113 _target_path: &str,
1114 _index_key: impl fmt::Debug,
1115 _detail: impl Sized,
1116 ) -> Self {
1117 Self::index_corruption()
1118 }
1119
1120 pub(crate) fn relation_target_store_missing(
1122 _source_path: &str,
1123 _field_name: &str,
1124 _target_path: &str,
1125 _store_path: &str,
1126 _detail: impl Sized,
1127 ) -> Self {
1128 Self::executor_internal()
1129 }
1130
1131 pub(crate) fn relation_target_key_decode_failed(
1133 _context_label: &str,
1134 _source_path: &str,
1135 _field_name: &str,
1136 _target_path: &str,
1137 _detail: impl Sized,
1138 ) -> Self {
1139 Self::identity_corruption()
1140 }
1141
1142 pub(crate) fn relation_target_entity_mismatch(
1144 _context_label: &str,
1145 _source_path: &str,
1146 _field_name: &str,
1147 _target_path: &str,
1148 _target_entity_name: &str,
1149 _expected_tag: impl Sized,
1150 _actual_tag: impl Sized,
1151 ) -> Self {
1152 Self::store_corruption()
1153 }
1154
1155 pub(crate) fn relation_source_row_decode_failed(
1157 _source_path: &str,
1158 _field_name: &str,
1159 _target_path: &str,
1160 _detail: impl Sized,
1161 ) -> Self {
1162 Self::persisted_row_decode_corruption()
1163 }
1164
1165 pub(crate) fn relation_source_row_unsupported_scalar_relation_key(
1167 _source_path: &str,
1168 _field_name: &str,
1169 _target_path: &str,
1170 ) -> Self {
1171 Self::persisted_row_decode_corruption()
1172 }
1173
1174 pub(crate) fn relation_source_row_unsupported_key_kind(_field_kind: impl fmt::Debug) -> Self {
1176 Self::persisted_row_decode_corruption()
1177 }
1178
1179 pub(crate) fn reverse_index_relation_target_decode_invariant_violated(
1181 _source_path: &str,
1182 _field_name: &str,
1183 _target_path: &str,
1184 ) -> Self {
1185 Self::executor_internal()
1186 }
1187
1188 pub(crate) fn bytes_covering_component_payload_empty() -> Self {
1190 Self::index_corruption()
1191 }
1192
1193 pub(crate) fn bytes_covering_bool_payload_truncated() -> Self {
1195 Self::index_corruption()
1196 }
1197
1198 pub(crate) fn bytes_covering_component_payload_invalid_length() -> Self {
1200 Self::index_corruption()
1201 }
1202
1203 pub(crate) fn bytes_covering_bool_payload_invalid_value() -> Self {
1205 Self::index_corruption()
1206 }
1207
1208 pub(crate) fn bytes_covering_text_payload_invalid_terminator() -> Self {
1210 Self::index_corruption()
1211 }
1212
1213 pub(crate) fn bytes_covering_text_payload_trailing_bytes() -> Self {
1215 Self::index_corruption()
1216 }
1217
1218 pub(crate) fn bytes_covering_text_payload_invalid_utf8() -> Self {
1220 Self::index_corruption()
1221 }
1222
1223 pub(crate) fn bytes_covering_text_payload_invalid_escape_byte() -> Self {
1225 Self::index_corruption()
1226 }
1227
1228 pub(crate) fn bytes_covering_text_payload_missing_terminator() -> Self {
1230 Self::index_corruption()
1231 }
1232
1233 #[must_use]
1235 pub fn missing_persisted_slot(field_name: &'static str) -> Self {
1236 Self::persisted_row_field_decode_corruption(field_name)
1237 }
1238
1239 pub(crate) fn identity_corruption() -> Self {
1241 Self::new(ErrorClass::Corruption, ErrorOrigin::Identity)
1242 }
1243
1244 #[cold]
1246 #[inline(never)]
1247 pub(crate) fn store_unsupported() -> Self {
1248 Self::new(ErrorClass::Unsupported, ErrorOrigin::Store)
1249 }
1250
1251 #[cfg(any(test, feature = "sql"))]
1253 pub(crate) fn schema_ddl_publication_race_lost(_entity_path: &'static str) -> Self {
1254 Self {
1255 class: ErrorClass::Unsupported,
1256 origin: ErrorOrigin::Store,
1257 detail: Some(ErrorDetail::Store(StoreError::SchemaDdlPublicationRaceLost)),
1258 }
1259 }
1260
1261 #[cfg(feature = "sql")]
1263 pub(crate) fn schema_ddl_rewrite_requires_migration(_entity_path: &'static str) -> Self {
1264 Self {
1265 class: ErrorClass::Unsupported,
1266 origin: ErrorOrigin::Store,
1267 detail: Some(ErrorDetail::Store(
1268 StoreError::SchemaDdlRewriteRequiresMigration,
1269 )),
1270 }
1271 }
1272
1273 pub(crate) fn schema_row_layout_version_exhausted() -> Self {
1275 Self {
1276 class: ErrorClass::Unsupported,
1277 origin: ErrorOrigin::Store,
1278 detail: Some(ErrorDetail::Store(
1279 StoreError::SchemaRowLayoutVersionExhausted,
1280 )),
1281 }
1282 }
1283
1284 pub(crate) fn journal_mutation_revision_exhausted() -> Self {
1286 Self {
1287 class: ErrorClass::Unsupported,
1288 origin: ErrorOrigin::Store,
1289 detail: Some(ErrorDetail::Store(
1290 StoreError::JournalMutationRevisionExhausted,
1291 )),
1292 }
1293 }
1294
1295 pub(crate) fn schema_generated_field_after_ddl_field() -> Self {
1298 Self {
1299 class: ErrorClass::Unsupported,
1300 origin: ErrorOrigin::Store,
1301 detail: Some(ErrorDetail::Store(
1302 StoreError::SchemaGeneratedFieldAfterDdlField,
1303 )),
1304 }
1305 }
1306
1307 pub(crate) fn schema_generated_constraint_activation_stale() -> Self {
1310 Self {
1311 class: ErrorClass::Conflict,
1312 origin: ErrorOrigin::Store,
1313 detail: Some(ErrorDetail::Store(
1314 StoreError::SchemaGeneratedConstraintActivationStale,
1315 )),
1316 }
1317 }
1318
1319 pub(crate) fn schema_transition_budget_exceeded(
1321 resource: SchemaTransitionBudgetResource,
1322 ) -> Self {
1323 Self {
1324 class: ErrorClass::Unsupported,
1325 origin: ErrorOrigin::Store,
1326 detail: Some(ErrorDetail::Store(
1327 StoreError::SchemaTransitionBudgetExceeded { resource },
1328 )),
1329 }
1330 }
1331
1332 pub(crate) fn unsupported_entity_tag_in_data_store(
1334 _entity_tag: crate::types::EntityTag,
1335 ) -> Self {
1336 Self::store_unsupported()
1337 }
1338
1339 #[cfg(not(test))]
1341 pub(crate) fn commit_memory_id_registration_failed(_err: impl Sized) -> Self {
1342 Self::store_internal()
1343 }
1344
1345 pub(crate) fn index_unsupported() -> Self {
1347 Self::new(ErrorClass::Unsupported, ErrorOrigin::Index)
1348 }
1349
1350 pub(crate) fn index_component_exceeds_max_size() -> Self {
1352 Self::index_unsupported()
1353 }
1354
1355 pub(crate) fn serialize_unsupported() -> Self {
1357 Self::new(ErrorClass::Unsupported, ErrorOrigin::Serialize)
1358 }
1359
1360 pub(crate) fn cursor_invalid_continuation() -> Self {
1362 Self::new(ErrorClass::Unsupported, ErrorOrigin::Cursor)
1363 }
1364
1365 pub(crate) fn serialize_incompatible_persisted_format() -> Self {
1367 Self::new(
1368 ErrorClass::IncompatiblePersistedFormat,
1369 ErrorOrigin::Serialize,
1370 )
1371 }
1372
1373 #[cfg(feature = "sql")]
1376 pub(crate) fn query_unsupported_sql_feature(feature: diagnostic_code::SqlFeatureCode) -> Self {
1377 Self {
1378 class: ErrorClass::Unsupported,
1379 origin: ErrorOrigin::Query,
1380 detail: Some(ErrorDetail::Query(
1381 QueryErrorDetail::UnsupportedSqlFeature { feature },
1382 )),
1383 }
1384 }
1385
1386 #[cfg(feature = "sql")]
1389 pub(crate) fn query_sql_lowering(reason: diagnostic_code::SqlLoweringCode) -> Self {
1390 Self {
1391 class: ErrorClass::Unsupported,
1392 origin: ErrorOrigin::Query,
1393 detail: Some(ErrorDetail::Query(QueryErrorDetail::SqlLowering { reason })),
1394 }
1395 }
1396
1397 pub(crate) fn query_unsupported_projection(
1400 reason: diagnostic_code::QueryProjectionCode,
1401 ) -> Self {
1402 Self {
1403 class: ErrorClass::Unsupported,
1404 origin: ErrorOrigin::Query,
1405 detail: Some(ErrorDetail::Query(
1406 QueryErrorDetail::UnsupportedProjection { reason },
1407 )),
1408 }
1409 }
1410
1411 pub(crate) fn query_unknown_aggregate_target_field() -> Self {
1413 Self {
1414 class: ErrorClass::Unsupported,
1415 origin: ErrorOrigin::Query,
1416 detail: Some(ErrorDetail::Query(
1417 QueryErrorDetail::UnknownAggregateTargetField,
1418 )),
1419 }
1420 }
1421
1422 pub(crate) fn query_result_shape_mismatch(
1425 reason: diagnostic_code::QueryResultShapeCode,
1426 ) -> Self {
1427 Self {
1428 class: ErrorClass::Unsupported,
1429 origin: ErrorOrigin::Query,
1430 detail: Some(ErrorDetail::Query(QueryErrorDetail::ResultShapeMismatch {
1431 reason,
1432 })),
1433 }
1434 }
1435
1436 #[cfg(feature = "sql")]
1439 pub(crate) fn query_sql_surface_mismatch(
1440 mismatch: diagnostic_code::SqlSurfaceMismatchCode,
1441 ) -> Self {
1442 Self {
1443 class: ErrorClass::Unsupported,
1444 origin: ErrorOrigin::Query,
1445 detail: Some(ErrorDetail::Query(QueryErrorDetail::SqlSurfaceMismatch {
1446 mismatch,
1447 })),
1448 }
1449 }
1450
1451 pub(crate) fn query_sql_write_boundary(
1453 boundary: diagnostic_code::SqlWriteBoundaryCode,
1454 ) -> Self {
1455 Self {
1456 class: ErrorClass::Unsupported,
1457 origin: ErrorOrigin::Query,
1458 detail: Some(ErrorDetail::Query(QueryErrorDetail::SqlWriteBoundary {
1459 boundary,
1460 })),
1461 }
1462 }
1463
1464 pub fn store_not_found(_key: impl Sized) -> Self {
1465 Self {
1466 class: ErrorClass::NotFound,
1467 origin: ErrorOrigin::Store,
1468 detail: Some(ErrorDetail::Store(StoreError::NotFound)),
1469 }
1470 }
1471
1472 pub fn unsupported_entity_path(_path: impl Sized) -> Self {
1474 Self::store_unsupported()
1475 }
1476
1477 #[must_use]
1478 pub const fn is_not_found(&self) -> bool {
1479 matches!(self.detail, Some(ErrorDetail::Store(StoreError::NotFound)))
1480 }
1481
1482 #[cold]
1484 #[inline(never)]
1485 pub(crate) fn index_plan_corruption(origin: ErrorOrigin) -> Self {
1486 Self::new(ErrorClass::Corruption, origin)
1487 }
1488
1489 #[cold]
1491 #[inline(never)]
1492 pub(crate) fn index_plan_index_corruption() -> Self {
1493 Self::index_plan_corruption(ErrorOrigin::Index)
1494 }
1495
1496 #[cold]
1498 #[inline(never)]
1499 pub(crate) fn index_plan_store_corruption() -> Self {
1500 Self::index_plan_corruption(ErrorOrigin::Store)
1501 }
1502
1503 #[cold]
1505 #[inline(never)]
1506 pub(crate) fn index_plan_serialize_corruption() -> Self {
1507 Self::index_plan_corruption(ErrorOrigin::Serialize)
1508 }
1509
1510 #[cfg(test)]
1512 pub(crate) fn index_plan_invariant(origin: ErrorOrigin) -> Self {
1513 Self::new(ErrorClass::InvariantViolation, origin)
1514 }
1515
1516 #[cfg(test)]
1518 pub(crate) fn index_plan_store_invariant() -> Self {
1519 Self::index_plan_invariant(ErrorOrigin::Store)
1520 }
1521
1522 pub(crate) fn index_violation(_path: &str, _index_fields: &[&str]) -> Self {
1524 Self::new(ErrorClass::Conflict, ErrorOrigin::Index)
1525 }
1526}
1527
1528impl From<diagnostic_code::QueryReadAdmissionCode> for InternalError {
1529 fn from(reason: diagnostic_code::QueryReadAdmissionCode) -> Self {
1530 Self {
1531 class: ErrorClass::Unsupported,
1532 origin: ErrorOrigin::Query,
1533 detail: Some(ErrorDetail::Query(QueryErrorDetail::QueryReadAdmission {
1534 reason,
1535 })),
1536 }
1537 }
1538}
1539
1540impl fmt::Debug for InternalError {
1541 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1542 fmt_compact_diagnostic(
1543 f,
1544 self.diagnostic_code(),
1545 self.detail
1546 .as_ref()
1547 .and_then(ErrorDetail::diagnostic_detail),
1548 )
1549 }
1550}
1551
1552impl fmt::Display for InternalError {
1553 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1554 f.write_str(self.message())
1555 }
1556}
1557
1558impl std::error::Error for InternalError {}
1559
1560#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq)]
1568pub enum ConstraintDiagnosticKind {
1569 Check,
1571
1572 NotNull,
1574
1575 Relation,
1577
1578 Unique,
1580}
1581
1582impl ConstraintDiagnosticKind {
1583 #[must_use]
1585 pub const fn as_str(self) -> &'static str {
1586 match self {
1587 Self::Check => "check",
1588 Self::NotNull => "not_null",
1589 Self::Relation => "relation",
1590 Self::Unique => "unique",
1591 }
1592 }
1593}
1594
1595#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq)]
1603pub enum ConstraintDiagnosticContext {
1604 Integrity,
1606
1607 MigrationValidation,
1609
1610 WriteAdmission,
1612}
1613
1614impl ConstraintDiagnosticContext {
1615 #[must_use]
1617 pub const fn as_str(self) -> &'static str {
1618 match self {
1619 Self::Integrity => "integrity",
1620 Self::MigrationValidation => "migration_validation",
1621 Self::WriteAdmission => "write_admission",
1622 }
1623 }
1624}
1625
1626#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
1635pub struct ConstraintDiagnostic {
1636 constraint_id: u32,
1637 constraint_name: String,
1638 constraint_kind: ConstraintDiagnosticKind,
1639 entity: String,
1640 primary_key: Option<Vec<u8>>,
1641 field_paths: Vec<String>,
1642 context: ConstraintDiagnosticContext,
1643 error_code: u16,
1644}
1645
1646impl ConstraintDiagnostic {
1647 #[must_use]
1649 pub(crate) const fn write_violation(
1650 constraint_id: u32,
1651 constraint_name: String,
1652 constraint_kind: ConstraintDiagnosticKind,
1653 entity: String,
1654 primary_key: Option<Vec<u8>>,
1655 field_paths: Vec<String>,
1656 ) -> Self {
1657 Self {
1658 constraint_id,
1659 constraint_name,
1660 constraint_kind,
1661 entity,
1662 primary_key,
1663 field_paths,
1664 context: ConstraintDiagnosticContext::WriteAdmission,
1665 error_code: diagnostic_code::ErrorCode::RUNTIME_BOUNDARY_CONSTRAINT_VIOLATION.raw(),
1666 }
1667 }
1668
1669 #[must_use]
1671 pub(crate) const fn write_activation_blocked(
1672 constraint_id: u32,
1673 constraint_name: String,
1674 constraint_kind: ConstraintDiagnosticKind,
1675 entity: String,
1676 primary_key: Option<Vec<u8>>,
1677 field_paths: Vec<String>,
1678 ) -> Self {
1679 Self {
1680 constraint_id,
1681 constraint_name,
1682 constraint_kind,
1683 entity,
1684 primary_key,
1685 field_paths,
1686 context: ConstraintDiagnosticContext::WriteAdmission,
1687 error_code:
1688 diagnostic_code::ErrorCode::RUNTIME_BOUNDARY_CONSTRAINT_ACTIVATION_WRITE_BLOCKED
1689 .raw(),
1690 }
1691 }
1692
1693 #[cfg(feature = "sql")]
1695 #[must_use]
1696 pub(crate) const fn migration_validation(
1697 constraint_id: u32,
1698 constraint_name: String,
1699 constraint_kind: ConstraintDiagnosticKind,
1700 entity: String,
1701 primary_key: Vec<u8>,
1702 field_paths: Vec<String>,
1703 error_code: u16,
1704 ) -> Self {
1705 Self {
1706 constraint_id,
1707 constraint_name,
1708 constraint_kind,
1709 entity,
1710 primary_key: Some(primary_key),
1711 field_paths,
1712 context: ConstraintDiagnosticContext::MigrationValidation,
1713 error_code,
1714 }
1715 }
1716
1717 #[must_use]
1719 pub const fn constraint_id(&self) -> u32 {
1720 self.constraint_id
1721 }
1722
1723 #[must_use]
1725 pub const fn constraint_name(&self) -> &str {
1726 self.constraint_name.as_str()
1727 }
1728
1729 #[must_use]
1731 pub const fn constraint_kind(&self) -> ConstraintDiagnosticKind {
1732 self.constraint_kind
1733 }
1734
1735 #[must_use]
1737 pub const fn entity(&self) -> &str {
1738 self.entity.as_str()
1739 }
1740
1741 #[must_use]
1743 pub fn primary_key(&self) -> Option<&[u8]> {
1744 self.primary_key.as_deref()
1745 }
1746
1747 #[must_use]
1749 pub const fn field_paths(&self) -> &[String] {
1750 self.field_paths.as_slice()
1751 }
1752
1753 #[must_use]
1755 pub const fn context(&self) -> ConstraintDiagnosticContext {
1756 self.context
1757 }
1758
1759 #[must_use]
1761 pub const fn error_code(&self) -> diagnostic_code::ErrorCode {
1762 diagnostic_code::ErrorCode::from_raw(self.error_code)
1763 }
1764
1765 #[must_use]
1767 pub const fn error_class(&self) -> diagnostic_code::ErrorClass {
1768 self.error_code().class()
1769 }
1770}
1771
1772pub enum ErrorDetail {
1780 Executor(ExecutorErrorDetail),
1782 Store(StoreError),
1783 Query(QueryErrorDetail),
1784 Recovery(RecoveryErrorDetail),
1785 Serialize(SerializeErrorDetail),
1787 }
1790
1791pub enum ExecutorErrorDetail {
1793 MutationRequiredFieldMissing,
1795 ConstraintViolation {
1797 diagnostic: Box<ConstraintDiagnostic>,
1798 },
1799 AcceptedRowConstraintProgramCorrupt,
1801 ConstraintActivationWriteBlocked {
1803 diagnostic: Box<ConstraintDiagnostic>,
1804 },
1805}
1806
1807impl ExecutorErrorDetail {
1808 #[must_use]
1810 pub fn constraint_diagnostic(&self) -> Option<&ConstraintDiagnostic> {
1811 match self {
1812 Self::ConstraintActivationWriteBlocked { diagnostic }
1813 | Self::ConstraintViolation { diagnostic } => Some(diagnostic.as_ref()),
1814 Self::MutationRequiredFieldMissing | Self::AcceptedRowConstraintProgramCorrupt => None,
1815 }
1816 }
1817}
1818
1819pub enum SerializeErrorDetail {
1821 PersistedRowLayoutOutsideAcceptedWindow,
1823
1824 PersistedRowSlotCountMismatch,
1826}
1827
1828pub enum RecoveryErrorDetail {
1835 UnsupportedFormatVersion { found: Option<u16>, required: u16 },
1836
1837 MalformedFormatMarker { reason: RecoveryFormatMarkerError },
1838}
1839
1840#[derive(Clone, Copy, Eq, PartialEq)]
1842pub enum RecoveryFormatMarkerError {
1843 Magic,
1844 Checksum,
1845 State,
1846}
1847
1848pub enum StoreError {
1856 NotFound,
1857
1858 Corrupt,
1859
1860 InvariantViolation,
1861
1862 SchemaDdlPublicationRaceLost,
1863
1864 SchemaDdlRewriteRequiresMigration,
1865
1866 SchemaRowLayoutVersionExhausted,
1867
1868 JournalMutationRevisionExhausted,
1869
1870 SchemaTransitionBudgetExceeded {
1871 resource: SchemaTransitionBudgetResource,
1872 },
1873
1874 SchemaGeneratedFieldAfterDdlField,
1876
1877 SchemaGeneratedConstraintActivationStale,
1879}
1880
1881pub enum QueryErrorDetail {
1888 NumericOverflow,
1889
1890 NumericNotRepresentable,
1891
1892 UnsupportedSqlFeature {
1893 feature: diagnostic_code::SqlFeatureCode,
1894 },
1895
1896 SqlLowering {
1897 reason: diagnostic_code::SqlLoweringCode,
1898 },
1899
1900 UnsupportedProjection {
1901 reason: diagnostic_code::QueryProjectionCode,
1902 },
1903
1904 UnknownAggregateTargetField,
1905
1906 ResultShapeMismatch {
1907 reason: diagnostic_code::QueryResultShapeCode,
1908 },
1909
1910 QueryReadAdmission {
1911 reason: diagnostic_code::QueryReadAdmissionCode,
1912 },
1913
1914 SqlSurfaceMismatch {
1915 mismatch: diagnostic_code::SqlSurfaceMismatchCode,
1916 },
1917
1918 SqlWriteBoundary {
1919 boundary: diagnostic_code::SqlWriteBoundaryCode,
1920 },
1921
1922 SchemaDdlAdmission {
1923 error: SchemaDdlAdmissionError,
1924 },
1925
1926 StaleSchemaRevision,
1927}
1928
1929impl fmt::Display for QueryErrorDetail {
1930 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1931 f.write_str(COMPACT_QUERY_DIAGNOSTIC_MESSAGE)
1932 }
1933}
1934
1935impl std::error::Error for QueryErrorDetail {}
1936
1937#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1945pub enum SchemaTransitionBudgetResource {
1946 DeletionKeys,
1948 ProjectionEntries,
1950 ProjectionWorkUnits,
1952 SourceRows,
1954 SourceRowBytes,
1956 StagedRawBytes,
1958}
1959
1960#[derive(Clone, Copy, Eq, PartialEq)]
1969pub enum SchemaDdlAdmissionError {
1970 MissingExpectedSchemaVersion,
1971
1972 MissingNextSchemaVersion,
1973
1974 StaleExpectedSchemaVersion,
1975
1976 InvalidExpectedSchemaVersion,
1977
1978 InvalidNextSchemaVersion,
1979
1980 AcceptedSchemaChangeWithoutVersionBump,
1981
1982 EmptyVersionBump,
1983
1984 VersionGap,
1985
1986 VersionRollback,
1987
1988 FingerprintMethodMismatch,
1989
1990 UnsupportedTransitionClass,
1991
1992 PhysicalRunnerMissing,
1993
1994 ValidationFailed,
1995
1996 PublicationRaceLost,
1997
1998 InvalidAddColumnDefault,
1999
2000 InvalidAlterColumnDefault,
2001
2002 RowLayoutVersionExhausted,
2003
2004 GeneratedIndexDropRejected,
2005
2006 SchemaRewriteRequiresMigration,
2007
2008 SchemaTransitionBudgetExceeded {
2009 resource: SchemaTransitionBudgetResource,
2010 },
2011
2012 GeneratedFieldDefaultChangeRejected,
2013
2014 GeneratedFieldNullabilityChangeRejected,
2015}
2016
2017impl fmt::Display for SchemaDdlAdmissionError {
2018 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2019 f.write_str(COMPACT_QUERY_DIAGNOSTIC_MESSAGE)
2020 }
2021}
2022
2023impl std::error::Error for SchemaDdlAdmissionError {}
2024
2025impl fmt::Debug for ErrorDetail {
2026 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2027 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2028 }
2029}
2030
2031impl fmt::Debug for ExecutorErrorDetail {
2032 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2033 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2034 }
2035}
2036
2037impl fmt::Debug for StoreError {
2038 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2039 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2040 }
2041}
2042
2043impl fmt::Debug for QueryErrorDetail {
2044 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2045 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2046 }
2047}
2048
2049impl fmt::Debug for RecoveryErrorDetail {
2050 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2051 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2052 }
2053}
2054
2055impl fmt::Debug for SerializeErrorDetail {
2056 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2057 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2058 }
2059}
2060
2061impl fmt::Debug for RecoveryFormatMarkerError {
2062 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2063 fmt_compact_diagnostic(
2064 f,
2065 diagnostic_code::DiagnosticCode::RuntimeCorruption,
2066 Some(diagnostic_code::DiagnosticDetail::RuntimeKind {
2067 kind: diagnostic_code::RuntimeErrorKind::Corruption,
2068 }),
2069 )
2070 }
2071}
2072
2073impl fmt::Debug for SchemaDdlAdmissionError {
2074 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2075 fmt_compact_diagnostic(
2076 f,
2077 diagnostic_code::DiagnosticCode::SchemaDdlAdmission,
2078 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2079 reason: self.diagnostic_code(),
2080 }),
2081 )
2082 }
2083}
2084
2085fn fmt_compact_diagnostic(
2086 f: &mut fmt::Formatter<'_>,
2087 code: diagnostic_code::DiagnosticCode,
2088 detail: Option<diagnostic_code::DiagnosticDetail>,
2089) -> fmt::Result {
2090 write!(
2091 f,
2092 "{}",
2093 diagnostic_code::ErrorCode::from_parts(code, detail).raw()
2094 )
2095}
2096
2097impl ErrorDetail {
2098 #[must_use]
2100 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2101 match self {
2102 Self::Executor(error) => error.diagnostic_code(),
2103 Self::Store(error) => error.diagnostic_code(),
2104 Self::Query(error) => error.diagnostic_code(),
2105 Self::Recovery(error) => error.diagnostic_code(),
2106 Self::Serialize(error) => error.diagnostic_code(),
2107 }
2108 }
2109
2110 #[must_use]
2112 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2113 match self {
2114 Self::Executor(error) => error.diagnostic_detail(),
2115 Self::Store(error) => error.diagnostic_detail(),
2116 Self::Query(error) => error.diagnostic_detail(),
2117 Self::Recovery(error) => error.diagnostic_detail(),
2118 Self::Serialize(error) => error.diagnostic_detail(),
2119 }
2120 }
2121}
2122
2123impl ExecutorErrorDetail {
2124 #[must_use]
2126 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2127 match self {
2128 Self::MutationRequiredFieldMissing => {
2129 diagnostic_code::DiagnosticCode::RuntimeUnsupported
2130 }
2131 Self::ConstraintViolation { diagnostic }
2132 | Self::ConstraintActivationWriteBlocked { diagnostic } => {
2133 diagnostic.error_code().diagnostic_code()
2134 }
2135 Self::AcceptedRowConstraintProgramCorrupt => {
2136 diagnostic_code::DiagnosticCode::RuntimeCorruption
2137 }
2138 }
2139 }
2140
2141 #[must_use]
2143 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2144 match self {
2145 Self::MutationRequiredFieldMissing => {
2146 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2147 boundary: diagnostic_code::RuntimeBoundaryCode::MutationRequiredFieldMissing,
2148 })
2149 }
2150 Self::ConstraintViolation { diagnostic }
2151 | Self::ConstraintActivationWriteBlocked { diagnostic } => {
2152 diagnostic.error_code().diagnostic_detail()
2153 }
2154 Self::AcceptedRowConstraintProgramCorrupt => {
2155 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2156 boundary:
2157 diagnostic_code::RuntimeBoundaryCode::AcceptedRowConstraintProgramCorrupt,
2158 })
2159 }
2160 }
2161 }
2162}
2163
2164impl RecoveryErrorDetail {
2165 #[must_use]
2167 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2168 match self {
2169 Self::UnsupportedFormatVersion { .. } => {
2170 diagnostic_code::DiagnosticCode::RuntimeIncompatiblePersistedFormat
2171 }
2172 Self::MalformedFormatMarker { .. } => {
2173 diagnostic_code::DiagnosticCode::RuntimeCorruption
2174 }
2175 }
2176 }
2177
2178 #[must_use]
2180 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2181 let kind = match self {
2182 Self::UnsupportedFormatVersion { .. } => {
2183 diagnostic_code::RuntimeErrorKind::IncompatiblePersistedFormat
2184 }
2185 Self::MalformedFormatMarker { .. } => diagnostic_code::RuntimeErrorKind::Corruption,
2186 };
2187
2188 Some(diagnostic_code::DiagnosticDetail::RuntimeKind { kind })
2189 }
2190}
2191
2192impl SerializeErrorDetail {
2193 #[must_use]
2195 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2196 match self {
2197 Self::PersistedRowLayoutOutsideAcceptedWindow | Self::PersistedRowSlotCountMismatch => {
2198 diagnostic_code::DiagnosticCode::RuntimeCorruption
2199 }
2200 }
2201 }
2202
2203 #[must_use]
2205 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2206 let boundary = match self {
2207 Self::PersistedRowLayoutOutsideAcceptedWindow => {
2208 diagnostic_code::RuntimeBoundaryCode::PersistedRowLayoutOutsideAcceptedWindow
2209 }
2210 Self::PersistedRowSlotCountMismatch => {
2211 diagnostic_code::RuntimeBoundaryCode::PersistedRowSlotCountMismatch
2212 }
2213 };
2214
2215 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary { boundary })
2216 }
2217}
2218
2219impl StoreError {
2220 #[must_use]
2222 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2223 match self {
2224 Self::NotFound => diagnostic_code::DiagnosticCode::StoreNotFound,
2225 Self::Corrupt => diagnostic_code::DiagnosticCode::StoreCorruption,
2226 Self::InvariantViolation => diagnostic_code::DiagnosticCode::StoreInvariantViolation,
2227 Self::SchemaDdlPublicationRaceLost
2228 | Self::SchemaDdlRewriteRequiresMigration
2229 | Self::SchemaRowLayoutVersionExhausted
2230 | Self::SchemaTransitionBudgetExceeded { .. } => {
2231 diagnostic_code::DiagnosticCode::SchemaDdlAdmission
2232 }
2233 Self::JournalMutationRevisionExhausted | Self::SchemaGeneratedFieldAfterDdlField => {
2234 diagnostic_code::DiagnosticCode::RuntimeUnsupported
2235 }
2236 Self::SchemaGeneratedConstraintActivationStale => {
2237 diagnostic_code::DiagnosticCode::RuntimeConflict
2238 }
2239 }
2240 }
2241
2242 #[must_use]
2244 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2245 match self {
2246 Self::SchemaDdlPublicationRaceLost => {
2247 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2248 reason: diagnostic_code::SchemaDdlAdmissionCode::PublicationRaceLost,
2249 })
2250 }
2251 Self::SchemaDdlRewriteRequiresMigration => {
2252 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2253 reason: diagnostic_code::SchemaDdlAdmissionCode::SchemaRewriteRequiresMigration,
2254 })
2255 }
2256 Self::SchemaRowLayoutVersionExhausted => {
2257 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2258 reason: diagnostic_code::SchemaDdlAdmissionCode::RowLayoutVersionExhausted,
2259 })
2260 }
2261 Self::JournalMutationRevisionExhausted => {
2262 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2263 boundary:
2264 diagnostic_code::RuntimeBoundaryCode::JournalMutationRevisionExhausted,
2265 })
2266 }
2267 Self::SchemaTransitionBudgetExceeded { .. } => {
2268 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2269 reason: diagnostic_code::SchemaDdlAdmissionCode::SchemaTransitionBudgetExceeded,
2270 })
2271 }
2272 Self::SchemaGeneratedFieldAfterDdlField => {
2273 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2274 boundary: diagnostic_code::RuntimeBoundaryCode::GeneratedFieldAfterDdlField,
2275 })
2276 }
2277 Self::SchemaGeneratedConstraintActivationStale => {
2278 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2279 boundary:
2280 diagnostic_code::RuntimeBoundaryCode::GeneratedConstraintActivationStale,
2281 })
2282 }
2283 Self::NotFound | Self::Corrupt | Self::InvariantViolation => None,
2284 }
2285 }
2286}
2287
2288impl QueryErrorDetail {
2289 #[must_use]
2291 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2292 match self {
2293 Self::NumericOverflow => diagnostic_code::DiagnosticCode::QueryNumericOverflow,
2294 Self::NumericNotRepresentable => {
2295 diagnostic_code::DiagnosticCode::QueryNumericNotRepresentable
2296 }
2297 Self::UnsupportedSqlFeature { .. } => {
2298 diagnostic_code::DiagnosticCode::QueryUnsupportedSqlFeature
2299 }
2300 Self::SqlLowering { .. } => diagnostic_code::DiagnosticCode::QueryUnsupportedSqlFeature,
2301 Self::UnsupportedProjection { .. } => {
2302 diagnostic_code::DiagnosticCode::QueryUnsupportedProjection
2303 }
2304 Self::UnknownAggregateTargetField => {
2305 diagnostic_code::DiagnosticCode::QueryUnknownAggregateTargetField
2306 }
2307 Self::ResultShapeMismatch { .. } => {
2308 diagnostic_code::DiagnosticCode::QueryResultShapeMismatch
2309 }
2310 Self::QueryReadAdmission { .. } => diagnostic_code::DiagnosticCode::QueryReadAdmission,
2311 Self::SqlSurfaceMismatch { .. } => {
2312 diagnostic_code::DiagnosticCode::QuerySqlSurfaceMismatch
2313 }
2314 Self::SqlWriteBoundary { .. } => diagnostic_code::DiagnosticCode::QuerySqlWriteBoundary,
2315 Self::SchemaDdlAdmission { .. } => diagnostic_code::DiagnosticCode::SchemaDdlAdmission,
2316 Self::StaleSchemaRevision => diagnostic_code::DiagnosticCode::RuntimeConflict,
2317 }
2318 }
2319
2320 #[must_use]
2322 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2323 match self {
2324 Self::UnsupportedSqlFeature { feature } => {
2325 Some(diagnostic_code::DiagnosticDetail::UnsupportedSqlFeature { feature: *feature })
2326 }
2327 Self::SqlLowering { reason } => {
2328 Some(diagnostic_code::DiagnosticDetail::SqlLowering { reason: *reason })
2329 }
2330 Self::UnsupportedProjection { reason } => {
2331 Some(diagnostic_code::DiagnosticDetail::QueryProjection { reason: *reason })
2332 }
2333 Self::ResultShapeMismatch { reason } => {
2334 Some(diagnostic_code::DiagnosticDetail::QueryResultShape { reason: *reason })
2335 }
2336 Self::QueryReadAdmission { reason } => {
2337 Some(diagnostic_code::DiagnosticDetail::QueryReadAdmission { reason: *reason })
2338 }
2339 Self::SqlSurfaceMismatch { mismatch } => {
2340 Some(diagnostic_code::DiagnosticDetail::SqlSurfaceMismatch {
2341 mismatch: *mismatch,
2342 })
2343 }
2344 Self::SqlWriteBoundary { boundary } => {
2345 Some(diagnostic_code::DiagnosticDetail::SqlWriteBoundary {
2346 boundary: *boundary,
2347 })
2348 }
2349 Self::SchemaDdlAdmission { error } => {
2350 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2351 reason: error.diagnostic_code(),
2352 })
2353 }
2354 Self::NumericOverflow
2355 | Self::NumericNotRepresentable
2356 | Self::UnknownAggregateTargetField
2357 | Self::StaleSchemaRevision => None,
2358 }
2359 }
2360}
2361
2362impl SchemaDdlAdmissionError {
2363 #[must_use]
2365 pub const fn diagnostic_code(&self) -> diagnostic_code::SchemaDdlAdmissionCode {
2366 match self {
2367 Self::MissingExpectedSchemaVersion => {
2368 diagnostic_code::SchemaDdlAdmissionCode::MissingExpectedSchemaVersion
2369 }
2370 Self::MissingNextSchemaVersion => {
2371 diagnostic_code::SchemaDdlAdmissionCode::MissingNextSchemaVersion
2372 }
2373 Self::StaleExpectedSchemaVersion => {
2374 diagnostic_code::SchemaDdlAdmissionCode::StaleExpectedSchemaVersion
2375 }
2376 Self::InvalidExpectedSchemaVersion => {
2377 diagnostic_code::SchemaDdlAdmissionCode::InvalidExpectedSchemaVersion
2378 }
2379 Self::InvalidNextSchemaVersion => {
2380 diagnostic_code::SchemaDdlAdmissionCode::InvalidNextSchemaVersion
2381 }
2382 Self::AcceptedSchemaChangeWithoutVersionBump => {
2383 diagnostic_code::SchemaDdlAdmissionCode::AcceptedSchemaChangeWithoutVersionBump
2384 }
2385 Self::EmptyVersionBump => diagnostic_code::SchemaDdlAdmissionCode::EmptyVersionBump,
2386 Self::VersionGap => diagnostic_code::SchemaDdlAdmissionCode::VersionGap,
2387 Self::VersionRollback => diagnostic_code::SchemaDdlAdmissionCode::VersionRollback,
2388 Self::FingerprintMethodMismatch => {
2389 diagnostic_code::SchemaDdlAdmissionCode::FingerprintMethodMismatch
2390 }
2391 Self::UnsupportedTransitionClass => {
2392 diagnostic_code::SchemaDdlAdmissionCode::UnsupportedTransitionClass
2393 }
2394 Self::PhysicalRunnerMissing => {
2395 diagnostic_code::SchemaDdlAdmissionCode::PhysicalRunnerMissing
2396 }
2397 Self::ValidationFailed => diagnostic_code::SchemaDdlAdmissionCode::ValidationFailed,
2398 Self::PublicationRaceLost => {
2399 diagnostic_code::SchemaDdlAdmissionCode::PublicationRaceLost
2400 }
2401 Self::InvalidAddColumnDefault => {
2402 diagnostic_code::SchemaDdlAdmissionCode::InvalidAddColumnDefault
2403 }
2404 Self::InvalidAlterColumnDefault => {
2405 diagnostic_code::SchemaDdlAdmissionCode::InvalidAlterColumnDefault
2406 }
2407 Self::GeneratedIndexDropRejected => {
2408 diagnostic_code::SchemaDdlAdmissionCode::GeneratedIndexDropRejected
2409 }
2410 Self::SchemaRewriteRequiresMigration => {
2411 diagnostic_code::SchemaDdlAdmissionCode::SchemaRewriteRequiresMigration
2412 }
2413 Self::SchemaTransitionBudgetExceeded { .. } => {
2414 diagnostic_code::SchemaDdlAdmissionCode::SchemaTransitionBudgetExceeded
2415 }
2416 Self::GeneratedFieldDefaultChangeRejected => {
2417 diagnostic_code::SchemaDdlAdmissionCode::GeneratedFieldDefaultChangeRejected
2418 }
2419 Self::GeneratedFieldNullabilityChangeRejected => {
2420 diagnostic_code::SchemaDdlAdmissionCode::GeneratedFieldNullabilityChangeRejected
2421 }
2422 Self::RowLayoutVersionExhausted => {
2423 diagnostic_code::SchemaDdlAdmissionCode::RowLayoutVersionExhausted
2424 }
2425 }
2426 }
2427}
2428
2429#[repr(u8)]
2436#[derive(Clone, Copy, Eq, PartialEq)]
2437pub enum ErrorClass {
2438 Corruption,
2439 IncompatiblePersistedFormat,
2440 NotFound,
2441 Internal,
2442 Conflict,
2443 Unsupported,
2444 InvariantViolation,
2445}
2446
2447impl ErrorClass {
2448 #[must_use]
2450 pub const fn diagnostic_code(self, origin: ErrorOrigin) -> diagnostic_code::DiagnosticCode {
2451 match self {
2452 Self::Corruption if matches!(origin, ErrorOrigin::Store) => {
2453 diagnostic_code::DiagnosticCode::StoreCorruption
2454 }
2455 Self::Corruption => diagnostic_code::DiagnosticCode::RuntimeCorruption,
2456 Self::IncompatiblePersistedFormat => {
2457 diagnostic_code::DiagnosticCode::RuntimeIncompatiblePersistedFormat
2458 }
2459 Self::NotFound if matches!(origin, ErrorOrigin::Store) => {
2460 diagnostic_code::DiagnosticCode::StoreNotFound
2461 }
2462 Self::NotFound => diagnostic_code::DiagnosticCode::RuntimeNotFound,
2463 Self::Internal => diagnostic_code::DiagnosticCode::RuntimeInternal,
2464 Self::Conflict => diagnostic_code::DiagnosticCode::RuntimeConflict,
2465 Self::Unsupported if matches!(origin, ErrorOrigin::Cursor) => {
2466 diagnostic_code::DiagnosticCode::QueryInvalidContinuationCursor
2467 }
2468 Self::Unsupported => diagnostic_code::DiagnosticCode::RuntimeUnsupported,
2469 Self::InvariantViolation if matches!(origin, ErrorOrigin::Store) => {
2470 diagnostic_code::DiagnosticCode::StoreInvariantViolation
2471 }
2472 Self::InvariantViolation => diagnostic_code::DiagnosticCode::RuntimeInvariantViolation,
2473 }
2474 }
2475}
2476
2477impl fmt::Debug for ErrorClass {
2478 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2479 write!(f, "{}", *self as u8)
2480 }
2481}
2482
2483#[repr(u8)]
2490#[derive(Clone, Copy, Eq, PartialEq)]
2491pub enum ErrorOrigin {
2492 Serialize,
2493 Store,
2494 Index,
2495 Identity,
2496 Query,
2497 Planner,
2498 Cursor,
2499 Recovery,
2500 Response,
2501 Executor,
2502 Interface,
2503}
2504
2505impl ErrorOrigin {
2506 #[must_use]
2508 pub const fn diagnostic_origin(self) -> diagnostic_code::ErrorOrigin {
2509 match self {
2510 Self::Serialize => diagnostic_code::ErrorOrigin::Serialize,
2511 Self::Store => diagnostic_code::ErrorOrigin::Store,
2512 Self::Index => diagnostic_code::ErrorOrigin::Index,
2513 Self::Identity => diagnostic_code::ErrorOrigin::Identity,
2514 Self::Query => diagnostic_code::ErrorOrigin::Query,
2515 Self::Planner => diagnostic_code::ErrorOrigin::Planner,
2516 Self::Cursor => diagnostic_code::ErrorOrigin::Cursor,
2517 Self::Recovery => diagnostic_code::ErrorOrigin::Recovery,
2518 Self::Response => diagnostic_code::ErrorOrigin::Response,
2519 Self::Executor => diagnostic_code::ErrorOrigin::Executor,
2520 Self::Interface => diagnostic_code::ErrorOrigin::Interface,
2521 }
2522 }
2523}
2524
2525impl fmt::Debug for ErrorOrigin {
2526 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2527 write!(f, "{}", *self as u8)
2528 }
2529}