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_conflict() -> Self {
322 Self::new(ErrorClass::Conflict, ErrorOrigin::Executor)
323 }
324
325 #[cold]
327 #[inline(never)]
328 pub(crate) fn executor_internal() -> Self {
329 Self::new(ErrorClass::Internal, ErrorOrigin::Executor)
330 }
331
332 #[cold]
334 #[inline(never)]
335 pub(crate) fn executor_unsupported() -> Self {
336 Self::new(ErrorClass::Unsupported, ErrorOrigin::Executor)
337 }
338
339 pub(crate) fn mutation_database_owned_field_explicit(
341 _entity_path: &str,
342 _field_name: &str,
343 ) -> Self {
344 Self {
345 class: ErrorClass::Unsupported,
346 origin: ErrorOrigin::Executor,
347 detail: Some(ErrorDetail::Executor(
348 ExecutorErrorDetail::MutationDatabaseOwnedFieldExplicit,
349 )),
350 }
351 }
352
353 #[must_use]
355 pub fn mutation_required_field_missing(_entity_path: &str, _field_names: &str) -> Self {
356 Self {
357 class: ErrorClass::Unsupported,
358 origin: ErrorOrigin::Executor,
359 detail: Some(ErrorDetail::Executor(
360 ExecutorErrorDetail::MutationRequiredFieldMissing,
361 )),
362 }
363 }
364
365 #[must_use]
367 pub(crate) fn mutation_managed_timestamp_regression() -> Self {
368 Self {
369 class: ErrorClass::InvariantViolation,
370 origin: ErrorOrigin::Executor,
371 detail: Some(ErrorDetail::Executor(
372 ExecutorErrorDetail::MutationManagedTimestampRegression,
373 )),
374 }
375 }
376
377 pub(crate) fn mutation_constraint_violation(diagnostic: ConstraintDiagnostic) -> Self {
379 Self {
380 class: ErrorClass::InvariantViolation,
381 origin: ErrorOrigin::Executor,
382 detail: Some(ErrorDetail::Executor(
383 ExecutorErrorDetail::ConstraintViolation {
384 diagnostic: Box::new(diagnostic),
385 },
386 )),
387 }
388 }
389
390 pub(crate) fn accepted_row_constraint_program_corrupt() -> Self {
392 Self {
393 class: ErrorClass::Corruption,
394 origin: ErrorOrigin::Executor,
395 detail: Some(ErrorDetail::Executor(
396 ExecutorErrorDetail::AcceptedRowConstraintProgramCorrupt,
397 )),
398 }
399 }
400
401 pub(crate) fn mutation_constraint_activation_write_blocked(
403 diagnostic: ConstraintDiagnostic,
404 ) -> Self {
405 Self {
406 class: ErrorClass::Conflict,
407 origin: ErrorOrigin::Executor,
408 detail: Some(ErrorDetail::Executor(
409 ExecutorErrorDetail::ConstraintActivationWriteBlocked {
410 diagnostic: Box::new(diagnostic),
411 },
412 )),
413 }
414 }
415
416 pub(crate) fn mutation_structural_field_unknown(_entity_path: &str, _field_name: &str) -> Self {
418 Self::executor_invariant()
419 }
420
421 #[cfg(any(test, feature = "query"))]
423 pub(crate) fn scalar_page_cursor_boundary_order_required() -> Self {
424 Self::query_executor_invariant()
425 }
426
427 #[cfg(any(test, feature = "query"))]
429 pub(crate) fn scalar_page_cursor_boundary_after_ordering_required() -> Self {
430 Self::query_executor_invariant()
431 }
432
433 #[cfg(any(test, feature = "query"))]
435 pub(crate) fn scalar_page_pagination_after_ordering_required() -> Self {
436 Self::query_executor_invariant()
437 }
438
439 #[cfg(any(test, feature = "query"))]
441 pub(crate) fn fast_stream_route_kind_request_match_required() -> Self {
442 Self::query_executor_invariant()
443 }
444
445 #[cfg(any(test, feature = "query"))]
447 pub(crate) fn secondary_index_prefix_spec_required() -> Self {
448 Self::query_executor_invariant()
449 }
450
451 #[cfg(any(test, feature = "query"))]
453 pub(crate) fn index_range_limit_spec_required() -> Self {
454 Self::query_executor_invariant()
455 }
456
457 pub(crate) fn mutation_atomic_save_duplicate_key(_entity_path: &str, _key: impl Sized) -> Self {
459 Self::executor_conflict()
460 }
461
462 pub(crate) fn mutation_index_store_generation_changed(
464 _expected_generation: u64,
465 _observed_generation: u64,
466 ) -> Self {
467 Self::executor_invariant()
468 }
469
470 #[cold]
472 #[inline(never)]
473 #[cfg(any(test, feature = "query"))]
474 pub(crate) fn planner_invariant() -> Self {
475 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Planner)
476 }
477
478 #[cfg(any(test, feature = "query"))]
480 pub(crate) fn query_invalid_logical_plan() -> Self {
481 Self::planner_invariant()
482 }
483
484 pub(crate) fn store_invariant() -> Self {
486 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Store)
487 }
488
489 #[cold]
491 #[inline(never)]
492 pub(crate) fn store_internal() -> Self {
493 Self::new(ErrorClass::Internal, ErrorOrigin::Store)
494 }
495
496 pub(crate) fn commit_memory_id_unconfigured() -> Self {
498 Self::store_internal()
499 }
500
501 pub(crate) fn commit_store_uninitialized() -> Self {
503 Self::store_invariant()
504 }
505
506 pub(crate) fn commit_memory_id_mismatch(_cached_id: u8, _configured_id: u8) -> Self {
508 Self::store_internal()
509 }
510
511 pub(crate) fn commit_memory_stable_key_mismatch(
513 _cached_key: &str,
514 _configured_key: &str,
515 ) -> Self {
516 Self::store_internal()
517 }
518
519 pub(crate) fn database_incarnation_generation_failed() -> Self {
521 Self::store_internal()
522 }
523
524 pub(crate) fn database_incarnation_invalid() -> Self {
526 Self::store_corruption()
527 }
528
529 pub(crate) fn recovery_unsupported_database_format(found: Option<u16>, required: u16) -> Self {
531 Self {
532 class: ErrorClass::IncompatiblePersistedFormat,
533 origin: ErrorOrigin::Recovery,
534 detail: Some(ErrorDetail::Recovery(
535 RecoveryErrorDetail::UnsupportedFormatVersion { found, required },
536 )),
537 }
538 }
539
540 pub(crate) fn recovery_malformed_database_format_marker(
542 reason: RecoveryFormatMarkerError,
543 ) -> Self {
544 Self {
545 class: ErrorClass::Corruption,
546 origin: ErrorOrigin::Recovery,
547 detail: Some(ErrorDetail::Recovery(
548 RecoveryErrorDetail::MalformedFormatMarker { reason },
549 )),
550 }
551 }
552
553 pub(crate) fn recovery_database_format_control_unavailable() -> Self {
555 Self::new(ErrorClass::Internal, ErrorOrigin::Recovery)
556 }
557
558 pub(crate) fn commit_control_memory_growth_failed() -> Self {
560 Self::store_internal()
561 }
562
563 #[cfg(not(test))]
565 pub(crate) fn database_format_memory_registration_failed(_err: impl Sized) -> Self {
566 Self::store_internal()
567 }
568
569 pub(crate) fn recovery_effect_verification_failed() -> Self {
571 Self::store_corruption()
572 }
573
574 #[cold]
576 #[inline(never)]
577 pub(crate) fn index_internal() -> Self {
578 Self::new(ErrorClass::Internal, ErrorOrigin::Index)
579 }
580
581 pub(crate) fn structural_index_removal_entity_key_required() -> Self {
583 Self::index_internal()
584 }
585
586 pub(crate) fn structural_index_insertion_entity_key_required() -> Self {
588 Self::index_internal()
589 }
590
591 pub(crate) fn index_commit_op_old_entity_key_required() -> Self {
593 Self::index_internal()
594 }
595
596 pub(crate) fn index_commit_op_new_entity_key_required() -> Self {
598 Self::index_internal()
599 }
600
601 #[cfg(test)]
603 pub(crate) fn query_internal() -> Self {
604 Self::new(ErrorClass::Internal, ErrorOrigin::Query)
605 }
606
607 #[cold]
609 #[inline(never)]
610 #[cfg(any(test, feature = "query"))]
611 pub(crate) fn query_unsupported() -> Self {
612 Self::new(ErrorClass::Unsupported, ErrorOrigin::Query)
613 }
614
615 #[cold]
618 #[inline(never)]
619 #[cfg(any(test, feature = "query"))]
620 pub(crate) fn query_stale_accepted_schema_revision(
621 _expected_revision: u64,
622 _current_revision: Option<u64>,
623 ) -> Self {
624 Self {
625 class: ErrorClass::Conflict,
626 origin: ErrorOrigin::Query,
627 detail: Some(ErrorDetail::Query(QueryErrorDetail::StaleSchemaRevision)),
628 }
629 }
630
631 #[cold]
633 #[inline(never)]
634 #[cfg(feature = "sql")]
635 pub(crate) fn query_schema_ddl_admission(error: SchemaDdlAdmissionError) -> Self {
636 Self {
637 class: ErrorClass::Unsupported,
638 origin: ErrorOrigin::Query,
639 detail: Some(ErrorDetail::Query(QueryErrorDetail::SchemaDdlAdmission {
640 error,
641 })),
642 }
643 }
644
645 #[cold]
647 #[inline(never)]
648 #[cfg(any(test, feature = "query"))]
649 pub(crate) fn query_numeric_overflow() -> Self {
650 Self {
651 class: ErrorClass::Unsupported,
652 origin: ErrorOrigin::Query,
653 detail: Some(ErrorDetail::Query(QueryErrorDetail::NumericOverflow)),
654 }
655 }
656
657 #[cold]
660 #[inline(never)]
661 #[cfg(any(test, feature = "query"))]
662 pub(crate) fn query_numeric_not_representable() -> Self {
663 Self {
664 class: ErrorClass::Unsupported,
665 origin: ErrorOrigin::Query,
666 detail: Some(ErrorDetail::Query(
667 QueryErrorDetail::NumericNotRepresentable,
668 )),
669 }
670 }
671
672 #[cold]
674 #[inline(never)]
675 pub(crate) fn serialize_internal() -> Self {
676 Self::new(ErrorClass::Internal, ErrorOrigin::Serialize)
677 }
678
679 pub(crate) fn persisted_row_encode_failed(_detail: impl Sized) -> Self {
681 Self::persisted_row_encode_internal()
682 }
683
684 pub(crate) fn persisted_row_encode_internal() -> Self {
686 Self::serialize_internal()
687 }
688
689 pub(crate) fn persisted_row_field_encode_internal(_field_name: &str) -> Self {
691 Self::persisted_row_encode_internal()
692 }
693
694 #[cold]
696 #[inline(never)]
697 pub(crate) fn store_corruption() -> Self {
698 Self::new(ErrorClass::Corruption, ErrorOrigin::Store)
699 }
700
701 pub(crate) fn commit_corruption() -> Self {
703 Self::store_corruption()
704 }
705
706 pub(crate) fn commit_component_corruption() -> Self {
708 Self::commit_corruption()
709 }
710
711 pub(crate) fn commit_id_generation_failed() -> Self {
713 Self::store_internal()
714 }
715
716 pub(crate) fn commit_marker_payload_exceeds_u32_length_limit() -> Self {
718 Self::store_unsupported()
719 }
720
721 pub(crate) fn commit_component_length_invalid() -> Self {
723 Self::commit_corruption()
724 }
725
726 pub(crate) fn commit_marker_exceeds_max_size() -> Self {
728 Self::commit_corruption()
729 }
730
731 pub(crate) fn commit_control_slot_exceeds_max_size() -> Self {
733 Self::store_unsupported()
734 }
735
736 pub(crate) fn commit_control_slot_marker_bytes_exceed_u32_length_limit() -> Self {
738 Self::store_unsupported()
739 }
740
741 pub(crate) fn startup_index_rebuild_invalid_data_key() -> Self {
743 Self::store_corruption()
744 }
745
746 #[cold]
748 #[inline(never)]
749 pub(crate) fn index_corruption() -> Self {
750 Self::new(ErrorClass::Corruption, ErrorOrigin::Index)
751 }
752
753 pub(crate) fn index_unique_validation_corruption() -> Self {
755 Self::index_plan_index_corruption()
756 }
757
758 pub(crate) fn structural_index_entry_corruption() -> Self {
760 Self::index_plan_index_corruption()
761 }
762
763 pub(crate) fn index_unique_validation_entity_key_required() -> Self {
765 Self::index_invariant()
766 }
767
768 pub(crate) fn index_unique_validation_row_deserialize_failed() -> Self {
770 Self::index_plan_serialize_corruption()
771 }
772
773 pub(crate) fn index_unique_validation_primary_key_decode_failed() -> Self {
775 Self::index_plan_serialize_corruption()
776 }
777
778 pub(crate) fn index_unique_validation_key_rebuild_failed() -> Self {
780 Self::index_plan_serialize_corruption()
781 }
782
783 pub(crate) fn index_unique_validation_row_required() -> Self {
785 Self::index_plan_store_corruption()
786 }
787
788 #[cfg(any(test, feature = "query"))]
790 pub(crate) fn index_only_predicate_component_required() -> Self {
791 Self::index_invariant()
792 }
793
794 #[cfg(any(test, feature = "query"))]
796 pub(crate) fn index_scan_continuation_anchor_within_envelope_required() -> Self {
797 Self::index_invariant()
798 }
799
800 #[cfg(any(test, feature = "query"))]
802 pub(crate) fn index_scan_continuation_advancement_required() -> Self {
803 Self::index_invariant()
804 }
805
806 #[cfg(any(test, feature = "query"))]
808 pub(crate) fn index_scan_key_corrupted_during(
809 _context: &'static str,
810 _err: impl Sized,
811 ) -> Self {
812 Self::index_corruption()
813 }
814
815 #[cfg(any(test, feature = "query"))]
817 pub(crate) fn index_projection_component_required(
818 _index_name: &str,
819 _component_index: usize,
820 ) -> Self {
821 Self::index_invariant()
822 }
823
824 #[cfg(any(test, feature = "query"))]
826 pub(crate) fn index_entry_decode_failed() -> Self {
827 Self::index_corruption()
828 }
829
830 pub(crate) fn serialize_corruption() -> Self {
832 Self::new(ErrorClass::Corruption, ErrorOrigin::Serialize)
833 }
834
835 pub(crate) fn persisted_row_decode_corruption() -> Self {
837 Self::serialize_corruption()
838 }
839
840 pub(crate) fn persisted_row_layout_outside_accepted_window() -> Self {
842 Self {
843 class: ErrorClass::Corruption,
844 origin: ErrorOrigin::Serialize,
845 detail: Some(ErrorDetail::Serialize(
846 SerializeErrorDetail::PersistedRowLayoutOutsideAcceptedWindow,
847 )),
848 }
849 }
850
851 pub(crate) fn persisted_row_slot_count_mismatch() -> Self {
853 Self {
854 class: ErrorClass::Corruption,
855 origin: ErrorOrigin::Serialize,
856 detail: Some(ErrorDetail::Serialize(
857 SerializeErrorDetail::PersistedRowSlotCountMismatch,
858 )),
859 }
860 }
861
862 pub(crate) fn persisted_row_field_decode_failed(field_name: &str, _detail: impl Sized) -> Self {
864 Self::persisted_row_field_decode_corruption(field_name)
865 }
866
867 pub(crate) fn persisted_row_field_decode_corruption(_field_name: &str) -> Self {
869 Self::persisted_row_decode_corruption()
870 }
871
872 pub(crate) fn persisted_row_field_kind_decode_failed(
874 field_name: &str,
875 _field_kind: impl fmt::Debug,
876 _detail: impl Sized,
877 ) -> Self {
878 Self::persisted_row_field_decode_corruption(field_name)
879 }
880
881 pub(crate) fn persisted_row_field_payload_exact_len_required(field_name: &str) -> Self {
883 Self::persisted_row_field_decode_corruption(field_name)
884 }
885
886 pub(crate) fn persisted_row_field_payload_must_be_empty(field_name: &str) -> Self {
888 Self::persisted_row_field_decode_corruption(field_name)
889 }
890
891 pub(crate) fn persisted_row_field_payload_invalid_byte(field_name: &str) -> Self {
893 Self::persisted_row_field_decode_corruption(field_name)
894 }
895
896 pub(crate) fn persisted_row_field_payload_non_finite(field_name: &str) -> Self {
898 Self::persisted_row_field_decode_corruption(field_name)
899 }
900
901 pub(crate) fn persisted_row_field_text_payload_invalid_utf8(field_name: &str) -> Self {
903 Self::persisted_row_field_decode_corruption(field_name)
904 }
905
906 pub(crate) fn persisted_row_slot_lookup_out_of_bounds(_model_path: &str, _slot: usize) -> Self {
908 Self::index_invariant()
909 }
910
911 pub(crate) fn persisted_row_slot_cache_lookup_out_of_bounds(
913 _model_path: &str,
914 _slot: usize,
915 ) -> Self {
916 Self::index_invariant()
917 }
918
919 pub(crate) fn persisted_row_primary_key_not_primary_key_encodable(
921 _data_key: impl fmt::Debug,
922 _detail: impl Sized,
923 ) -> Self {
924 Self::persisted_row_decode_corruption()
925 }
926
927 pub(crate) fn persisted_row_primary_key_slot_missing(_data_key: impl fmt::Debug) -> Self {
929 Self::persisted_row_decode_corruption()
930 }
931
932 pub(crate) fn persisted_row_key_mismatch() -> Self {
934 Self::store_corruption()
935 }
936
937 pub(crate) fn persisted_row_declared_field_missing(field_name: &str) -> Self {
939 Self::persisted_row_field_decode_corruption(field_name)
940 }
941
942 pub(crate) fn reverse_index_ordinal_overflow(
944 _source_path: &str,
945 _field_name: &str,
946 _target_path: &str,
947 _detail: impl Sized,
948 ) -> Self {
949 Self::index_internal()
950 }
951
952 pub(crate) fn reverse_index_entry_corrupted(
954 _source_path: &str,
955 _field_name: &str,
956 _target_path: &str,
957 _index_key: impl fmt::Debug,
958 _detail: impl Sized,
959 ) -> Self {
960 Self::index_corruption()
961 }
962
963 pub(crate) fn relation_target_store_missing(
965 _source_path: &str,
966 _field_name: &str,
967 _target_path: &str,
968 _store_path: &str,
969 _detail: impl Sized,
970 ) -> Self {
971 Self::executor_internal()
972 }
973
974 pub(crate) fn relation_target_key_decode_failed(
976 _context_label: &str,
977 _source_path: &str,
978 _field_name: &str,
979 _target_path: &str,
980 _detail: impl Sized,
981 ) -> Self {
982 Self::identity_corruption()
983 }
984
985 pub(crate) fn relation_target_entity_mismatch(
987 _context_label: &str,
988 _source_path: &str,
989 _field_name: &str,
990 _target_path: &str,
991 _target_entity_name: &str,
992 _expected_tag: impl Sized,
993 _actual_tag: impl Sized,
994 ) -> Self {
995 Self::store_corruption()
996 }
997
998 pub(crate) fn relation_source_row_decode_failed(
1000 _source_path: &str,
1001 _field_name: &str,
1002 _target_path: &str,
1003 _detail: impl Sized,
1004 ) -> Self {
1005 Self::persisted_row_decode_corruption()
1006 }
1007
1008 pub(crate) fn relation_source_row_unsupported_scalar_relation_key(
1010 _source_path: &str,
1011 _field_name: &str,
1012 _target_path: &str,
1013 ) -> Self {
1014 Self::persisted_row_decode_corruption()
1015 }
1016
1017 pub(crate) fn relation_source_row_unsupported_key_kind(_field_kind: impl fmt::Debug) -> Self {
1019 Self::persisted_row_decode_corruption()
1020 }
1021
1022 #[cfg(any(test, feature = "query"))]
1024 pub(crate) fn bytes_covering_component_payload_empty() -> Self {
1025 Self::index_corruption()
1026 }
1027
1028 #[cfg(any(test, feature = "query"))]
1030 pub(crate) fn bytes_covering_bool_payload_truncated() -> Self {
1031 Self::index_corruption()
1032 }
1033
1034 #[cfg(any(test, feature = "query"))]
1036 pub(crate) fn bytes_covering_component_payload_invalid_length() -> Self {
1037 Self::index_corruption()
1038 }
1039
1040 #[cfg(any(test, feature = "query"))]
1042 pub(crate) fn bytes_covering_bool_payload_invalid_value() -> Self {
1043 Self::index_corruption()
1044 }
1045
1046 #[cfg(any(test, feature = "query"))]
1048 pub(crate) fn bytes_covering_text_payload_invalid_terminator() -> Self {
1049 Self::index_corruption()
1050 }
1051
1052 #[cfg(any(test, feature = "query"))]
1054 pub(crate) fn bytes_covering_text_payload_trailing_bytes() -> Self {
1055 Self::index_corruption()
1056 }
1057
1058 #[cfg(any(test, feature = "query"))]
1060 pub(crate) fn bytes_covering_text_payload_invalid_utf8() -> Self {
1061 Self::index_corruption()
1062 }
1063
1064 #[cfg(any(test, feature = "query"))]
1066 pub(crate) fn bytes_covering_text_payload_invalid_escape_byte() -> Self {
1067 Self::index_corruption()
1068 }
1069
1070 #[cfg(any(test, feature = "query"))]
1072 pub(crate) fn bytes_covering_text_payload_missing_terminator() -> Self {
1073 Self::index_corruption()
1074 }
1075
1076 #[must_use]
1078 pub fn missing_persisted_slot(field_name: &'static str) -> Self {
1079 Self::persisted_row_field_decode_corruption(field_name)
1080 }
1081
1082 pub(crate) fn identity_corruption() -> Self {
1084 Self::new(ErrorClass::Corruption, ErrorOrigin::Identity)
1085 }
1086
1087 pub(crate) fn identity_state_corruption() -> Self {
1089 Self::identity_corruption()
1090 }
1091
1092 pub(crate) fn identity_state_conflict() -> Self {
1094 Self::new(ErrorClass::Conflict, ErrorOrigin::Identity)
1095 }
1096
1097 pub(crate) fn identity_state_capacity_exhausted() -> Self {
1099 Self::new(ErrorClass::Unsupported, ErrorOrigin::Identity)
1100 }
1101
1102 pub(crate) fn identity_exhausted() -> Self {
1104 Self::new(ErrorClass::Unsupported, ErrorOrigin::Identity)
1105 }
1106
1107 pub(crate) fn identity_candidate_count_exhausted() -> Self {
1109 Self::new(ErrorClass::Unsupported, ErrorOrigin::Identity)
1110 }
1111
1112 #[cold]
1114 #[inline(never)]
1115 pub(crate) fn store_unsupported() -> Self {
1116 Self::new(ErrorClass::Unsupported, ErrorOrigin::Store)
1117 }
1118
1119 pub(crate) fn schema_application_conflict() -> Self {
1121 Self::new(ErrorClass::Conflict, ErrorOrigin::Store)
1122 }
1123
1124 #[cfg(any(test, feature = "query"))]
1126 pub(crate) fn schema_ddl_publication_race_lost(_entity_path: &str) -> Self {
1127 Self {
1128 class: ErrorClass::Unsupported,
1129 origin: ErrorOrigin::Store,
1130 detail: Some(ErrorDetail::Store(StoreError::SchemaDdlPublicationRaceLost)),
1131 }
1132 }
1133
1134 #[cfg(feature = "sql")]
1136 pub(crate) fn schema_ddl_rewrite_requires_migration(_entity_path: &str) -> Self {
1137 Self {
1138 class: ErrorClass::Unsupported,
1139 origin: ErrorOrigin::Store,
1140 detail: Some(ErrorDetail::Store(
1141 StoreError::SchemaDdlRewriteRequiresMigration,
1142 )),
1143 }
1144 }
1145
1146 pub(crate) fn journal_mutation_revision_exhausted() -> Self {
1148 Self {
1149 class: ErrorClass::Unsupported,
1150 origin: ErrorOrigin::Store,
1151 detail: Some(ErrorDetail::Store(
1152 StoreError::JournalMutationRevisionExhausted,
1153 )),
1154 }
1155 }
1156
1157 pub(crate) fn schema_transition_budget_exceeded(
1159 resource: SchemaTransitionBudgetResource,
1160 ) -> Self {
1161 Self {
1162 class: ErrorClass::Unsupported,
1163 origin: ErrorOrigin::Store,
1164 detail: Some(ErrorDetail::Store(
1165 StoreError::SchemaTransitionBudgetExceeded { resource },
1166 )),
1167 }
1168 }
1169
1170 pub(crate) fn unsupported_entity_tag_in_data_store(
1172 _entity_tag: crate::types::EntityTag,
1173 ) -> Self {
1174 Self::store_unsupported()
1175 }
1176
1177 #[cfg(not(test))]
1179 pub(crate) fn commit_memory_id_registration_failed(_err: impl Sized) -> Self {
1180 Self::store_internal()
1181 }
1182
1183 pub(crate) fn index_unsupported() -> Self {
1185 Self::new(ErrorClass::Unsupported, ErrorOrigin::Index)
1186 }
1187
1188 pub(crate) fn index_component_exceeds_max_size() -> Self {
1190 Self::index_unsupported()
1191 }
1192
1193 pub(crate) fn serialize_unsupported() -> Self {
1195 Self::new(ErrorClass::Unsupported, ErrorOrigin::Serialize)
1196 }
1197
1198 #[cfg(any(test, feature = "query"))]
1200 pub(crate) fn cursor_invalid_continuation() -> Self {
1201 Self::new(ErrorClass::Unsupported, ErrorOrigin::Cursor)
1202 }
1203
1204 pub(crate) fn serialize_incompatible_persisted_format() -> Self {
1206 Self::new(
1207 ErrorClass::IncompatiblePersistedFormat,
1208 ErrorOrigin::Serialize,
1209 )
1210 }
1211
1212 #[cfg(feature = "sql")]
1215 pub(crate) fn query_unsupported_sql_feature(feature: diagnostic_code::SqlFeatureCode) -> Self {
1216 Self {
1217 class: ErrorClass::Unsupported,
1218 origin: ErrorOrigin::Query,
1219 detail: Some(ErrorDetail::Query(
1220 QueryErrorDetail::UnsupportedSqlFeature { feature },
1221 )),
1222 }
1223 }
1224
1225 #[cfg(feature = "sql")]
1228 pub(crate) fn query_sql_lowering(reason: diagnostic_code::SqlLoweringCode) -> Self {
1229 Self {
1230 class: ErrorClass::Unsupported,
1231 origin: ErrorOrigin::Query,
1232 detail: Some(ErrorDetail::Query(QueryErrorDetail::SqlLowering { reason })),
1233 }
1234 }
1235
1236 #[cfg(any(test, feature = "query"))]
1239 pub(crate) fn query_unsupported_projection(
1240 reason: diagnostic_code::QueryProjectionCode,
1241 ) -> Self {
1242 Self {
1243 class: ErrorClass::Unsupported,
1244 origin: ErrorOrigin::Query,
1245 detail: Some(ErrorDetail::Query(
1246 QueryErrorDetail::UnsupportedProjection { reason },
1247 )),
1248 }
1249 }
1250
1251 #[cfg(any(test, feature = "query"))]
1253 pub(crate) fn query_unknown_aggregate_target_field() -> Self {
1254 Self {
1255 class: ErrorClass::Unsupported,
1256 origin: ErrorOrigin::Query,
1257 detail: Some(ErrorDetail::Query(
1258 QueryErrorDetail::UnknownAggregateTargetField,
1259 )),
1260 }
1261 }
1262
1263 #[cfg(feature = "sql")]
1266 pub(crate) fn query_sql_surface_mismatch(
1267 mismatch: diagnostic_code::SqlSurfaceMismatchCode,
1268 ) -> Self {
1269 Self {
1270 class: ErrorClass::Unsupported,
1271 origin: ErrorOrigin::Query,
1272 detail: Some(ErrorDetail::Query(QueryErrorDetail::SqlSurfaceMismatch {
1273 mismatch,
1274 })),
1275 }
1276 }
1277
1278 pub(crate) fn query_sql_write_boundary(
1280 boundary: diagnostic_code::SqlWriteBoundaryCode,
1281 ) -> Self {
1282 Self {
1283 class: ErrorClass::Unsupported,
1284 origin: ErrorOrigin::Query,
1285 detail: Some(ErrorDetail::Query(QueryErrorDetail::SqlWriteBoundary {
1286 boundary,
1287 })),
1288 }
1289 }
1290
1291 pub fn store_not_found(_key: impl Sized) -> Self {
1292 Self {
1293 class: ErrorClass::NotFound,
1294 origin: ErrorOrigin::Store,
1295 detail: Some(ErrorDetail::Store(StoreError::NotFound)),
1296 }
1297 }
1298
1299 pub fn unsupported_entity_path(_path: impl Sized) -> Self {
1301 Self::store_unsupported()
1302 }
1303
1304 #[must_use]
1305 pub const fn is_not_found(&self) -> bool {
1306 matches!(self.detail, Some(ErrorDetail::Store(StoreError::NotFound)))
1307 }
1308
1309 #[cold]
1311 #[inline(never)]
1312 pub(crate) fn index_plan_corruption(origin: ErrorOrigin) -> Self {
1313 Self::new(ErrorClass::Corruption, origin)
1314 }
1315
1316 #[cold]
1318 #[inline(never)]
1319 pub(crate) fn index_plan_index_corruption() -> Self {
1320 Self::index_plan_corruption(ErrorOrigin::Index)
1321 }
1322
1323 #[cold]
1325 #[inline(never)]
1326 pub(crate) fn index_plan_store_corruption() -> Self {
1327 Self::index_plan_corruption(ErrorOrigin::Store)
1328 }
1329
1330 #[cold]
1332 #[inline(never)]
1333 pub(crate) fn index_plan_serialize_corruption() -> Self {
1334 Self::index_plan_corruption(ErrorOrigin::Serialize)
1335 }
1336
1337 #[cfg(test)]
1339 pub(crate) fn index_plan_invariant(origin: ErrorOrigin) -> Self {
1340 Self::new(ErrorClass::InvariantViolation, origin)
1341 }
1342
1343 #[cfg(test)]
1345 pub(crate) fn index_plan_store_invariant() -> Self {
1346 Self::index_plan_invariant(ErrorOrigin::Store)
1347 }
1348
1349 pub(crate) fn index_conflict() -> Self {
1355 Self::new(ErrorClass::Conflict, ErrorOrigin::Index)
1356 }
1357}
1358
1359impl From<diagnostic_code::QueryReadAdmissionCode> for InternalError {
1360 fn from(reason: diagnostic_code::QueryReadAdmissionCode) -> Self {
1361 Self {
1362 class: ErrorClass::Unsupported,
1363 origin: ErrorOrigin::Query,
1364 detail: Some(ErrorDetail::Query(QueryErrorDetail::QueryReadAdmission {
1365 reason,
1366 })),
1367 }
1368 }
1369}
1370
1371impl fmt::Debug for InternalError {
1372 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1373 fmt_compact_diagnostic(
1374 f,
1375 self.diagnostic_code(),
1376 self.detail
1377 .as_ref()
1378 .and_then(ErrorDetail::diagnostic_detail),
1379 )
1380 }
1381}
1382
1383impl fmt::Display for InternalError {
1384 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1385 f.write_str(self.message())
1386 }
1387}
1388
1389impl std::error::Error for InternalError {}
1390
1391#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq)]
1399pub enum ConstraintDiagnosticKind {
1400 Check,
1402
1403 NotNull,
1405
1406 Relation,
1408
1409 TargetedRule,
1411
1412 Unique,
1414}
1415
1416impl ConstraintDiagnosticKind {
1417 #[must_use]
1419 pub const fn as_str(self) -> &'static str {
1420 match self {
1421 Self::Check => "check",
1422 Self::NotNull => "not_null",
1423 Self::Relation => "relation",
1424 Self::TargetedRule => "targeted_rule",
1425 Self::Unique => "unique",
1426 }
1427 }
1428}
1429
1430#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq)]
1439pub enum ConstraintValuePathComponent {
1440 RootField { field_id: u32 },
1442
1443 RecordMember {
1445 composite_type_id: u32,
1446 member_id: u32,
1447 },
1448
1449 TupleElement {
1451 composite_type_id: u32,
1452 ordinal: u32,
1453 },
1454
1455 Newtype { composite_type_id: u32 },
1457
1458 EnumVariant { enum_type_id: u32, variant_id: u32 },
1460
1461 ListElement { index: u32 },
1463
1464 SetElement { index: u32 },
1466
1467 MapEntryKey { index: u32 },
1469
1470 MapEntryValue { index: u32 },
1472}
1473
1474impl fmt::Display for ConstraintValuePathComponent {
1475 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1476 match self {
1477 Self::RootField { field_id } => write!(f, "field#{field_id}"),
1478 Self::RecordMember {
1479 composite_type_id,
1480 member_id,
1481 } => write!(f, "record#{composite_type_id}.member#{member_id}"),
1482 Self::TupleElement {
1483 composite_type_id,
1484 ordinal,
1485 } => write!(f, "tuple#{composite_type_id}[{ordinal}]"),
1486 Self::Newtype { composite_type_id } => write!(f, "newtype#{composite_type_id}"),
1487 Self::EnumVariant {
1488 enum_type_id,
1489 variant_id,
1490 } => write!(f, "enum#{enum_type_id}.variant#{variant_id}"),
1491 Self::ListElement { index } => write!(f, "list[{index}]"),
1492 Self::SetElement { index } => write!(f, "set[{index}]"),
1493 Self::MapEntryKey { index } => write!(f, "map[{index}].key"),
1494 Self::MapEntryValue { index } => write!(f, "map[{index}].value"),
1495 }
1496 }
1497}
1498
1499#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
1506pub struct ConstraintValuePath {
1507 components: Vec<ConstraintValuePathComponent>,
1508}
1509
1510impl ConstraintValuePath {
1511 #[must_use]
1513 pub(crate) const fn new(components: Vec<ConstraintValuePathComponent>) -> Self {
1514 Self { components }
1515 }
1516
1517 #[must_use]
1519 pub const fn components(&self) -> &[ConstraintValuePathComponent] {
1520 self.components.as_slice()
1521 }
1522}
1523
1524impl fmt::Display for ConstraintValuePath {
1525 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1526 for (ordinal, component) in self.components.iter().enumerate() {
1527 if ordinal != 0 {
1528 f.write_str("/")?;
1529 }
1530 component.fmt(f)?;
1531 }
1532 Ok(())
1533 }
1534}
1535
1536#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq)]
1544pub enum ConstraintDiagnosticContext {
1545 Integrity,
1547
1548 MigrationValidation,
1550
1551 WriteAdmission,
1553}
1554
1555impl ConstraintDiagnosticContext {
1556 #[must_use]
1558 pub const fn as_str(self) -> &'static str {
1559 match self {
1560 Self::Integrity => "integrity",
1561 Self::MigrationValidation => "migration_validation",
1562 Self::WriteAdmission => "write_admission",
1563 }
1564 }
1565}
1566
1567#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
1576pub struct ConstraintDiagnostic {
1577 constraint_id: u32,
1578 constraint_name: String,
1579 constraint_kind: ConstraintDiagnosticKind,
1580 entity: String,
1581 primary_key: Option<Vec<u8>>,
1582 field_paths: Vec<String>,
1583 value_path: Option<Box<ConstraintValuePath>>,
1584 context: ConstraintDiagnosticContext,
1585 error_code: u16,
1586}
1587
1588impl ConstraintDiagnostic {
1589 #[must_use]
1591 pub(crate) const fn write_violation(
1592 constraint_id: u32,
1593 constraint_name: String,
1594 constraint_kind: ConstraintDiagnosticKind,
1595 entity: String,
1596 primary_key: Option<Vec<u8>>,
1597 field_paths: Vec<String>,
1598 ) -> Self {
1599 Self {
1600 constraint_id,
1601 constraint_name,
1602 constraint_kind,
1603 entity,
1604 primary_key,
1605 field_paths,
1606 value_path: None,
1607 context: ConstraintDiagnosticContext::WriteAdmission,
1608 error_code: diagnostic_code::ErrorCode::RUNTIME_BOUNDARY_CONSTRAINT_VIOLATION.raw(),
1609 }
1610 }
1611
1612 #[must_use]
1614 pub(crate) fn write_targeted_rule_violation(
1615 constraint_id: u32,
1616 constraint_name: String,
1617 entity: String,
1618 primary_key: Option<Vec<u8>>,
1619 field_paths: Vec<String>,
1620 value_path: ConstraintValuePath,
1621 ) -> Self {
1622 Self {
1623 constraint_id,
1624 constraint_name,
1625 constraint_kind: ConstraintDiagnosticKind::TargetedRule,
1626 entity,
1627 primary_key,
1628 field_paths,
1629 value_path: Some(Box::new(value_path)),
1630 context: ConstraintDiagnosticContext::WriteAdmission,
1631 error_code: diagnostic_code::ErrorCode::RUNTIME_BOUNDARY_CONSTRAINT_VIOLATION.raw(),
1632 }
1633 }
1634
1635 #[must_use]
1637 pub(crate) const fn write_activation_blocked(
1638 constraint_id: u32,
1639 constraint_name: String,
1640 constraint_kind: ConstraintDiagnosticKind,
1641 entity: String,
1642 primary_key: Option<Vec<u8>>,
1643 field_paths: Vec<String>,
1644 ) -> Self {
1645 Self {
1646 constraint_id,
1647 constraint_name,
1648 constraint_kind,
1649 entity,
1650 primary_key,
1651 field_paths,
1652 value_path: None,
1653 context: ConstraintDiagnosticContext::WriteAdmission,
1654 error_code:
1655 diagnostic_code::ErrorCode::RUNTIME_BOUNDARY_CONSTRAINT_ACTIVATION_WRITE_BLOCKED
1656 .raw(),
1657 }
1658 }
1659
1660 #[must_use]
1662 pub(crate) const fn migration_validation(
1663 constraint_id: u32,
1664 constraint_name: String,
1665 constraint_kind: ConstraintDiagnosticKind,
1666 entity: String,
1667 primary_key: Vec<u8>,
1668 field_paths: Vec<String>,
1669 error_code: u16,
1670 ) -> Self {
1671 Self {
1672 constraint_id,
1673 constraint_name,
1674 constraint_kind,
1675 entity,
1676 primary_key: Some(primary_key),
1677 field_paths,
1678 value_path: None,
1679 context: ConstraintDiagnosticContext::MigrationValidation,
1680 error_code,
1681 }
1682 }
1683
1684 #[must_use]
1686 pub(crate) fn migration_targeted_rule_validation(
1687 constraint_id: u32,
1688 constraint_name: String,
1689 entity: String,
1690 primary_key: Vec<u8>,
1691 field_paths: Vec<String>,
1692 value_path: ConstraintValuePath,
1693 error_code: u16,
1694 ) -> Self {
1695 Self {
1696 constraint_id,
1697 constraint_name,
1698 constraint_kind: ConstraintDiagnosticKind::TargetedRule,
1699 entity,
1700 primary_key: Some(primary_key),
1701 field_paths,
1702 value_path: Some(Box::new(value_path)),
1703 context: ConstraintDiagnosticContext::MigrationValidation,
1704 error_code,
1705 }
1706 }
1707
1708 #[must_use]
1710 pub const fn constraint_id(&self) -> u32 {
1711 self.constraint_id
1712 }
1713
1714 #[must_use]
1716 pub const fn constraint_name(&self) -> &str {
1717 self.constraint_name.as_str()
1718 }
1719
1720 #[must_use]
1722 pub const fn constraint_kind(&self) -> ConstraintDiagnosticKind {
1723 self.constraint_kind
1724 }
1725
1726 #[must_use]
1728 pub const fn entity(&self) -> &str {
1729 self.entity.as_str()
1730 }
1731
1732 #[must_use]
1734 pub fn primary_key(&self) -> Option<&[u8]> {
1735 self.primary_key.as_deref()
1736 }
1737
1738 #[must_use]
1740 pub const fn field_paths(&self) -> &[String] {
1741 self.field_paths.as_slice()
1742 }
1743
1744 #[must_use]
1746 pub fn value_path(&self) -> Option<&ConstraintValuePath> {
1747 self.value_path.as_deref()
1748 }
1749
1750 #[must_use]
1752 pub const fn context(&self) -> ConstraintDiagnosticContext {
1753 self.context
1754 }
1755
1756 #[must_use]
1758 pub const fn error_code(&self) -> diagnostic_code::ErrorCode {
1759 diagnostic_code::ErrorCode::from_raw(self.error_code)
1760 }
1761
1762 #[must_use]
1764 pub const fn error_class(&self) -> diagnostic_code::ErrorClass {
1765 self.error_code().class()
1766 }
1767}
1768
1769pub enum ErrorDetail {
1777 Executor(ExecutorErrorDetail),
1779 Store(StoreError),
1780 Query(QueryErrorDetail),
1781 Recovery(RecoveryErrorDetail),
1782 Serialize(SerializeErrorDetail),
1784 }
1787
1788pub enum ExecutorErrorDetail {
1790 MutationRequiredFieldMissing,
1792 MutationManagedTimestampRegression,
1794 MutationDatabaseOwnedFieldExplicit,
1796 ConstraintViolation {
1798 diagnostic: Box<ConstraintDiagnostic>,
1799 },
1800 AcceptedRowConstraintProgramCorrupt,
1802 ConstraintActivationWriteBlocked {
1804 diagnostic: Box<ConstraintDiagnostic>,
1805 },
1806}
1807
1808impl ExecutorErrorDetail {
1809 #[must_use]
1811 pub fn constraint_diagnostic(&self) -> Option<&ConstraintDiagnostic> {
1812 match self {
1813 Self::ConstraintActivationWriteBlocked { diagnostic }
1814 | Self::ConstraintViolation { diagnostic } => Some(diagnostic.as_ref()),
1815 Self::MutationRequiredFieldMissing
1816 | Self::MutationManagedTimestampRegression
1817 | Self::MutationDatabaseOwnedFieldExplicit
1818 | Self::AcceptedRowConstraintProgramCorrupt => None,
1819 }
1820 }
1821}
1822
1823pub enum SerializeErrorDetail {
1825 PersistedRowLayoutOutsideAcceptedWindow,
1827
1828 PersistedRowSlotCountMismatch,
1830}
1831
1832pub enum RecoveryErrorDetail {
1839 UnsupportedFormatVersion { found: Option<u16>, required: u16 },
1840
1841 MalformedFormatMarker { reason: RecoveryFormatMarkerError },
1842}
1843
1844#[derive(Clone, Copy, Eq, PartialEq)]
1846pub enum RecoveryFormatMarkerError {
1847 Magic,
1848 Checksum,
1849 State,
1850}
1851
1852pub enum StoreError {
1860 NotFound,
1861
1862 Corrupt,
1863
1864 InvariantViolation,
1865
1866 SchemaDdlPublicationRaceLost,
1867
1868 SchemaDdlRewriteRequiresMigration,
1869
1870 SchemaRowLayoutVersionExhausted,
1871
1872 JournalMutationRevisionExhausted,
1873
1874 SchemaTransitionBudgetExceeded {
1875 resource: SchemaTransitionBudgetResource,
1876 },
1877
1878 SchemaGeneratedFieldAfterDdlField,
1880
1881 SchemaGeneratedConstraintActivationStale,
1883}
1884
1885pub enum QueryErrorDetail {
1892 NumericOverflow,
1893
1894 NumericNotRepresentable,
1895
1896 UnsupportedSqlFeature {
1897 feature: diagnostic_code::SqlFeatureCode,
1898 },
1899
1900 SqlLowering {
1901 reason: diagnostic_code::SqlLoweringCode,
1902 },
1903
1904 UnsupportedProjection {
1905 reason: diagnostic_code::QueryProjectionCode,
1906 },
1907
1908 UnknownAggregateTargetField,
1909
1910 ResultShapeMismatch {
1911 reason: diagnostic_code::QueryResultShapeCode,
1912 },
1913
1914 QueryReadAdmission {
1915 reason: diagnostic_code::QueryReadAdmissionCode,
1916 },
1917
1918 SqlSurfaceMismatch {
1919 mismatch: diagnostic_code::SqlSurfaceMismatchCode,
1920 },
1921
1922 SqlWriteBoundary {
1923 boundary: diagnostic_code::SqlWriteBoundaryCode,
1924 },
1925
1926 SchemaDdlAdmission {
1927 error: SchemaDdlAdmissionError,
1928 },
1929
1930 StaleSchemaRevision,
1931}
1932
1933impl fmt::Display for QueryErrorDetail {
1934 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1935 f.write_str(COMPACT_QUERY_DIAGNOSTIC_MESSAGE)
1936 }
1937}
1938
1939impl std::error::Error for QueryErrorDetail {}
1940
1941#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1949pub enum SchemaTransitionBudgetResource {
1950 DeletionKeys,
1952 ProjectionEntries,
1954 ProjectionWorkUnits,
1956 SourceRows,
1958 SourceRowBytes,
1960 StagedRawBytes,
1962}
1963
1964#[derive(Clone, Copy, Eq, PartialEq)]
1973pub enum SchemaDdlAdmissionError {
1974 MissingExpectedSchemaVersion,
1975
1976 MissingNextSchemaVersion,
1977
1978 StaleExpectedSchemaVersion,
1979
1980 InvalidExpectedSchemaVersion,
1981
1982 InvalidNextSchemaVersion,
1983
1984 AcceptedSchemaChangeWithoutVersionBump,
1985
1986 EmptyVersionBump,
1987
1988 VersionGap,
1989
1990 VersionRollback,
1991
1992 FingerprintMethodMismatch,
1993
1994 UnsupportedTransitionClass,
1995
1996 PhysicalRunnerMissing,
1997
1998 ValidationFailed,
1999
2000 PublicationRaceLost,
2001
2002 InvalidAddColumnDefault,
2003
2004 InvalidAlterColumnDefault,
2005
2006 RowLayoutVersionExhausted,
2007
2008 GeneratedIndexDropRejected,
2009
2010 SchemaRewriteRequiresMigration,
2011
2012 SchemaTransitionBudgetExceeded {
2013 resource: SchemaTransitionBudgetResource,
2014 },
2015
2016 GeneratedFieldDefaultChangeRejected,
2017
2018 GeneratedFieldNullabilityChangeRejected,
2019}
2020
2021impl fmt::Display for SchemaDdlAdmissionError {
2022 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2023 f.write_str(COMPACT_QUERY_DIAGNOSTIC_MESSAGE)
2024 }
2025}
2026
2027impl std::error::Error for SchemaDdlAdmissionError {}
2028
2029impl fmt::Debug for ErrorDetail {
2030 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2031 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2032 }
2033}
2034
2035impl fmt::Debug for ExecutorErrorDetail {
2036 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2037 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2038 }
2039}
2040
2041impl fmt::Debug for StoreError {
2042 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2043 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2044 }
2045}
2046
2047impl fmt::Debug for QueryErrorDetail {
2048 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2049 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2050 }
2051}
2052
2053impl fmt::Debug for RecoveryErrorDetail {
2054 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2055 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2056 }
2057}
2058
2059impl fmt::Debug for SerializeErrorDetail {
2060 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2061 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2062 }
2063}
2064
2065impl fmt::Debug for RecoveryFormatMarkerError {
2066 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2067 fmt_compact_diagnostic(
2068 f,
2069 diagnostic_code::DiagnosticCode::RuntimeCorruption,
2070 Some(diagnostic_code::DiagnosticDetail::RuntimeKind {
2071 kind: diagnostic_code::RuntimeErrorKind::Corruption,
2072 }),
2073 )
2074 }
2075}
2076
2077impl fmt::Debug for SchemaDdlAdmissionError {
2078 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2079 fmt_compact_diagnostic(
2080 f,
2081 diagnostic_code::DiagnosticCode::SchemaDdlAdmission,
2082 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2083 reason: self.diagnostic_code(),
2084 }),
2085 )
2086 }
2087}
2088
2089fn fmt_compact_diagnostic(
2090 f: &mut fmt::Formatter<'_>,
2091 code: diagnostic_code::DiagnosticCode,
2092 detail: Option<diagnostic_code::DiagnosticDetail>,
2093) -> fmt::Result {
2094 write!(
2095 f,
2096 "{}",
2097 diagnostic_code::ErrorCode::from_parts(code, detail).raw()
2098 )
2099}
2100
2101impl ErrorDetail {
2102 #[must_use]
2104 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2105 match self {
2106 Self::Executor(error) => error.diagnostic_code(),
2107 Self::Store(error) => error.diagnostic_code(),
2108 Self::Query(error) => error.diagnostic_code(),
2109 Self::Recovery(error) => error.diagnostic_code(),
2110 Self::Serialize(error) => error.diagnostic_code(),
2111 }
2112 }
2113
2114 #[must_use]
2116 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2117 match self {
2118 Self::Executor(error) => error.diagnostic_detail(),
2119 Self::Store(error) => error.diagnostic_detail(),
2120 Self::Query(error) => error.diagnostic_detail(),
2121 Self::Recovery(error) => error.diagnostic_detail(),
2122 Self::Serialize(error) => error.diagnostic_detail(),
2123 }
2124 }
2125}
2126
2127impl ExecutorErrorDetail {
2128 #[must_use]
2130 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2131 match self {
2132 Self::MutationRequiredFieldMissing | Self::MutationDatabaseOwnedFieldExplicit => {
2133 diagnostic_code::DiagnosticCode::RuntimeUnsupported
2134 }
2135 Self::MutationManagedTimestampRegression => {
2136 diagnostic_code::DiagnosticCode::RuntimeInvariantViolation
2137 }
2138 Self::ConstraintViolation { diagnostic }
2139 | Self::ConstraintActivationWriteBlocked { diagnostic } => {
2140 diagnostic.error_code().diagnostic_code()
2141 }
2142 Self::AcceptedRowConstraintProgramCorrupt => {
2143 diagnostic_code::DiagnosticCode::RuntimeCorruption
2144 }
2145 }
2146 }
2147
2148 #[must_use]
2150 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2151 match self {
2152 Self::MutationRequiredFieldMissing => {
2153 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2154 boundary: diagnostic_code::RuntimeBoundaryCode::MutationRequiredFieldMissing,
2155 })
2156 }
2157 Self::MutationDatabaseOwnedFieldExplicit => {
2158 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2159 boundary:
2160 diagnostic_code::RuntimeBoundaryCode::MutationDatabaseOwnedFieldExplicit,
2161 })
2162 }
2163 Self::MutationManagedTimestampRegression => {
2164 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2165 boundary:
2166 diagnostic_code::RuntimeBoundaryCode::MutationManagedTimestampRegression,
2167 })
2168 }
2169 Self::ConstraintViolation { diagnostic }
2170 | Self::ConstraintActivationWriteBlocked { diagnostic } => {
2171 diagnostic.error_code().diagnostic_detail()
2172 }
2173 Self::AcceptedRowConstraintProgramCorrupt => {
2174 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2175 boundary:
2176 diagnostic_code::RuntimeBoundaryCode::AcceptedRowConstraintProgramCorrupt,
2177 })
2178 }
2179 }
2180 }
2181}
2182
2183impl RecoveryErrorDetail {
2184 #[must_use]
2186 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2187 match self {
2188 Self::UnsupportedFormatVersion { .. } => {
2189 diagnostic_code::DiagnosticCode::RuntimeIncompatiblePersistedFormat
2190 }
2191 Self::MalformedFormatMarker { .. } => {
2192 diagnostic_code::DiagnosticCode::RuntimeCorruption
2193 }
2194 }
2195 }
2196
2197 #[must_use]
2199 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2200 let kind = match self {
2201 Self::UnsupportedFormatVersion { .. } => {
2202 diagnostic_code::RuntimeErrorKind::IncompatiblePersistedFormat
2203 }
2204 Self::MalformedFormatMarker { .. } => diagnostic_code::RuntimeErrorKind::Corruption,
2205 };
2206
2207 Some(diagnostic_code::DiagnosticDetail::RuntimeKind { kind })
2208 }
2209}
2210
2211impl SerializeErrorDetail {
2212 #[must_use]
2214 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2215 match self {
2216 Self::PersistedRowLayoutOutsideAcceptedWindow | Self::PersistedRowSlotCountMismatch => {
2217 diagnostic_code::DiagnosticCode::RuntimeCorruption
2218 }
2219 }
2220 }
2221
2222 #[must_use]
2224 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2225 let boundary = match self {
2226 Self::PersistedRowLayoutOutsideAcceptedWindow => {
2227 diagnostic_code::RuntimeBoundaryCode::PersistedRowLayoutOutsideAcceptedWindow
2228 }
2229 Self::PersistedRowSlotCountMismatch => {
2230 diagnostic_code::RuntimeBoundaryCode::PersistedRowSlotCountMismatch
2231 }
2232 };
2233
2234 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary { boundary })
2235 }
2236}
2237
2238impl StoreError {
2239 #[must_use]
2241 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2242 match self {
2243 Self::NotFound => diagnostic_code::DiagnosticCode::StoreNotFound,
2244 Self::Corrupt => diagnostic_code::DiagnosticCode::StoreCorruption,
2245 Self::InvariantViolation => diagnostic_code::DiagnosticCode::StoreInvariantViolation,
2246 Self::SchemaDdlPublicationRaceLost
2247 | Self::SchemaDdlRewriteRequiresMigration
2248 | Self::SchemaRowLayoutVersionExhausted
2249 | Self::SchemaTransitionBudgetExceeded { .. } => {
2250 diagnostic_code::DiagnosticCode::SchemaDdlAdmission
2251 }
2252 Self::JournalMutationRevisionExhausted | Self::SchemaGeneratedFieldAfterDdlField => {
2253 diagnostic_code::DiagnosticCode::RuntimeUnsupported
2254 }
2255 Self::SchemaGeneratedConstraintActivationStale => {
2256 diagnostic_code::DiagnosticCode::RuntimeConflict
2257 }
2258 }
2259 }
2260
2261 #[must_use]
2263 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2264 match self {
2265 Self::SchemaDdlPublicationRaceLost => {
2266 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2267 reason: diagnostic_code::SchemaDdlAdmissionCode::PublicationRaceLost,
2268 })
2269 }
2270 Self::SchemaDdlRewriteRequiresMigration => {
2271 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2272 reason: diagnostic_code::SchemaDdlAdmissionCode::SchemaRewriteRequiresMigration,
2273 })
2274 }
2275 Self::SchemaRowLayoutVersionExhausted => {
2276 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2277 reason: diagnostic_code::SchemaDdlAdmissionCode::RowLayoutVersionExhausted,
2278 })
2279 }
2280 Self::JournalMutationRevisionExhausted => {
2281 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2282 boundary:
2283 diagnostic_code::RuntimeBoundaryCode::JournalMutationRevisionExhausted,
2284 })
2285 }
2286 Self::SchemaTransitionBudgetExceeded { .. } => {
2287 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2288 reason: diagnostic_code::SchemaDdlAdmissionCode::SchemaTransitionBudgetExceeded,
2289 })
2290 }
2291 Self::SchemaGeneratedFieldAfterDdlField => {
2292 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2293 boundary: diagnostic_code::RuntimeBoundaryCode::GeneratedFieldAfterDdlField,
2294 })
2295 }
2296 Self::SchemaGeneratedConstraintActivationStale => {
2297 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2298 boundary:
2299 diagnostic_code::RuntimeBoundaryCode::GeneratedConstraintActivationStale,
2300 })
2301 }
2302 Self::NotFound | Self::Corrupt | Self::InvariantViolation => None,
2303 }
2304 }
2305}
2306
2307impl QueryErrorDetail {
2308 #[must_use]
2310 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2311 match self {
2312 Self::NumericOverflow => diagnostic_code::DiagnosticCode::QueryNumericOverflow,
2313 Self::NumericNotRepresentable => {
2314 diagnostic_code::DiagnosticCode::QueryNumericNotRepresentable
2315 }
2316 Self::UnsupportedSqlFeature { .. } => {
2317 diagnostic_code::DiagnosticCode::QueryUnsupportedSqlFeature
2318 }
2319 Self::SqlLowering { .. } => diagnostic_code::DiagnosticCode::QueryUnsupportedSqlFeature,
2320 Self::UnsupportedProjection { .. } => {
2321 diagnostic_code::DiagnosticCode::QueryUnsupportedProjection
2322 }
2323 Self::UnknownAggregateTargetField => {
2324 diagnostic_code::DiagnosticCode::QueryUnknownAggregateTargetField
2325 }
2326 Self::ResultShapeMismatch { .. } => {
2327 diagnostic_code::DiagnosticCode::QueryResultShapeMismatch
2328 }
2329 Self::QueryReadAdmission { .. } => diagnostic_code::DiagnosticCode::QueryReadAdmission,
2330 Self::SqlSurfaceMismatch { .. } => {
2331 diagnostic_code::DiagnosticCode::QuerySqlSurfaceMismatch
2332 }
2333 Self::SqlWriteBoundary { .. } => diagnostic_code::DiagnosticCode::QuerySqlWriteBoundary,
2334 Self::SchemaDdlAdmission { .. } => diagnostic_code::DiagnosticCode::SchemaDdlAdmission,
2335 Self::StaleSchemaRevision => diagnostic_code::DiagnosticCode::RuntimeConflict,
2336 }
2337 }
2338
2339 #[must_use]
2341 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2342 match self {
2343 Self::UnsupportedSqlFeature { feature } => {
2344 Some(diagnostic_code::DiagnosticDetail::UnsupportedSqlFeature { feature: *feature })
2345 }
2346 Self::SqlLowering { reason } => {
2347 Some(diagnostic_code::DiagnosticDetail::SqlLowering { reason: *reason })
2348 }
2349 Self::UnsupportedProjection { reason } => {
2350 Some(diagnostic_code::DiagnosticDetail::QueryProjection { reason: *reason })
2351 }
2352 Self::ResultShapeMismatch { reason } => {
2353 Some(diagnostic_code::DiagnosticDetail::QueryResultShape { reason: *reason })
2354 }
2355 Self::QueryReadAdmission { reason } => {
2356 Some(diagnostic_code::DiagnosticDetail::QueryReadAdmission { reason: *reason })
2357 }
2358 Self::SqlSurfaceMismatch { mismatch } => {
2359 Some(diagnostic_code::DiagnosticDetail::SqlSurfaceMismatch {
2360 mismatch: *mismatch,
2361 })
2362 }
2363 Self::SqlWriteBoundary { boundary } => {
2364 Some(diagnostic_code::DiagnosticDetail::SqlWriteBoundary {
2365 boundary: *boundary,
2366 })
2367 }
2368 Self::SchemaDdlAdmission { error } => {
2369 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2370 reason: error.diagnostic_code(),
2371 })
2372 }
2373 Self::NumericOverflow
2374 | Self::NumericNotRepresentable
2375 | Self::UnknownAggregateTargetField
2376 | Self::StaleSchemaRevision => None,
2377 }
2378 }
2379}
2380
2381impl SchemaDdlAdmissionError {
2382 #[must_use]
2384 pub const fn diagnostic_code(&self) -> diagnostic_code::SchemaDdlAdmissionCode {
2385 match self {
2386 Self::MissingExpectedSchemaVersion => {
2387 diagnostic_code::SchemaDdlAdmissionCode::MissingExpectedSchemaVersion
2388 }
2389 Self::MissingNextSchemaVersion => {
2390 diagnostic_code::SchemaDdlAdmissionCode::MissingNextSchemaVersion
2391 }
2392 Self::StaleExpectedSchemaVersion => {
2393 diagnostic_code::SchemaDdlAdmissionCode::StaleExpectedSchemaVersion
2394 }
2395 Self::InvalidExpectedSchemaVersion => {
2396 diagnostic_code::SchemaDdlAdmissionCode::InvalidExpectedSchemaVersion
2397 }
2398 Self::InvalidNextSchemaVersion => {
2399 diagnostic_code::SchemaDdlAdmissionCode::InvalidNextSchemaVersion
2400 }
2401 Self::AcceptedSchemaChangeWithoutVersionBump => {
2402 diagnostic_code::SchemaDdlAdmissionCode::AcceptedSchemaChangeWithoutVersionBump
2403 }
2404 Self::EmptyVersionBump => diagnostic_code::SchemaDdlAdmissionCode::EmptyVersionBump,
2405 Self::VersionGap => diagnostic_code::SchemaDdlAdmissionCode::VersionGap,
2406 Self::VersionRollback => diagnostic_code::SchemaDdlAdmissionCode::VersionRollback,
2407 Self::FingerprintMethodMismatch => {
2408 diagnostic_code::SchemaDdlAdmissionCode::FingerprintMethodMismatch
2409 }
2410 Self::UnsupportedTransitionClass => {
2411 diagnostic_code::SchemaDdlAdmissionCode::UnsupportedTransitionClass
2412 }
2413 Self::PhysicalRunnerMissing => {
2414 diagnostic_code::SchemaDdlAdmissionCode::PhysicalRunnerMissing
2415 }
2416 Self::ValidationFailed => diagnostic_code::SchemaDdlAdmissionCode::ValidationFailed,
2417 Self::PublicationRaceLost => {
2418 diagnostic_code::SchemaDdlAdmissionCode::PublicationRaceLost
2419 }
2420 Self::InvalidAddColumnDefault => {
2421 diagnostic_code::SchemaDdlAdmissionCode::InvalidAddColumnDefault
2422 }
2423 Self::InvalidAlterColumnDefault => {
2424 diagnostic_code::SchemaDdlAdmissionCode::InvalidAlterColumnDefault
2425 }
2426 Self::GeneratedIndexDropRejected => {
2427 diagnostic_code::SchemaDdlAdmissionCode::GeneratedIndexDropRejected
2428 }
2429 Self::SchemaRewriteRequiresMigration => {
2430 diagnostic_code::SchemaDdlAdmissionCode::SchemaRewriteRequiresMigration
2431 }
2432 Self::SchemaTransitionBudgetExceeded { .. } => {
2433 diagnostic_code::SchemaDdlAdmissionCode::SchemaTransitionBudgetExceeded
2434 }
2435 Self::GeneratedFieldDefaultChangeRejected => {
2436 diagnostic_code::SchemaDdlAdmissionCode::GeneratedFieldDefaultChangeRejected
2437 }
2438 Self::GeneratedFieldNullabilityChangeRejected => {
2439 diagnostic_code::SchemaDdlAdmissionCode::GeneratedFieldNullabilityChangeRejected
2440 }
2441 Self::RowLayoutVersionExhausted => {
2442 diagnostic_code::SchemaDdlAdmissionCode::RowLayoutVersionExhausted
2443 }
2444 }
2445 }
2446}
2447
2448#[repr(u8)]
2455#[derive(Clone, Copy, Eq, PartialEq)]
2456pub enum ErrorClass {
2457 Corruption,
2458 IncompatiblePersistedFormat,
2459 NotFound,
2460 Internal,
2461 Conflict,
2462 Unsupported,
2463 InvariantViolation,
2464}
2465
2466impl ErrorClass {
2467 #[must_use]
2469 pub const fn diagnostic_code(self, origin: ErrorOrigin) -> diagnostic_code::DiagnosticCode {
2470 match self {
2471 Self::Corruption if matches!(origin, ErrorOrigin::Store) => {
2472 diagnostic_code::DiagnosticCode::StoreCorruption
2473 }
2474 Self::Corruption => diagnostic_code::DiagnosticCode::RuntimeCorruption,
2475 Self::IncompatiblePersistedFormat => {
2476 diagnostic_code::DiagnosticCode::RuntimeIncompatiblePersistedFormat
2477 }
2478 Self::NotFound if matches!(origin, ErrorOrigin::Store) => {
2479 diagnostic_code::DiagnosticCode::StoreNotFound
2480 }
2481 Self::NotFound => diagnostic_code::DiagnosticCode::RuntimeNotFound,
2482 Self::Internal => diagnostic_code::DiagnosticCode::RuntimeInternal,
2483 Self::Conflict => diagnostic_code::DiagnosticCode::RuntimeConflict,
2484 Self::Unsupported if matches!(origin, ErrorOrigin::Cursor) => {
2485 diagnostic_code::DiagnosticCode::QueryInvalidContinuationCursor
2486 }
2487 Self::Unsupported => diagnostic_code::DiagnosticCode::RuntimeUnsupported,
2488 Self::InvariantViolation if matches!(origin, ErrorOrigin::Store) => {
2489 diagnostic_code::DiagnosticCode::StoreInvariantViolation
2490 }
2491 Self::InvariantViolation => diagnostic_code::DiagnosticCode::RuntimeInvariantViolation,
2492 }
2493 }
2494}
2495
2496impl fmt::Debug for ErrorClass {
2497 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2498 write!(f, "{}", *self as u8)
2499 }
2500}
2501
2502#[repr(u8)]
2509#[derive(Clone, Copy, Eq, PartialEq)]
2510pub enum ErrorOrigin {
2511 Serialize,
2512 Store,
2513 Index,
2514 Identity,
2515 Query,
2516 Planner,
2517 Cursor,
2518 Recovery,
2519 Response,
2520 Executor,
2521 Interface,
2522}
2523
2524impl ErrorOrigin {
2525 #[must_use]
2527 pub const fn diagnostic_origin(self) -> diagnostic_code::ErrorOrigin {
2528 match self {
2529 Self::Serialize => diagnostic_code::ErrorOrigin::Serialize,
2530 Self::Store => diagnostic_code::ErrorOrigin::Store,
2531 Self::Index => diagnostic_code::ErrorOrigin::Index,
2532 Self::Identity => diagnostic_code::ErrorOrigin::Identity,
2533 Self::Query => diagnostic_code::ErrorOrigin::Query,
2534 Self::Planner => diagnostic_code::ErrorOrigin::Planner,
2535 Self::Cursor => diagnostic_code::ErrorOrigin::Cursor,
2536 Self::Recovery => diagnostic_code::ErrorOrigin::Recovery,
2537 Self::Response => diagnostic_code::ErrorOrigin::Response,
2538 Self::Executor => diagnostic_code::ErrorOrigin::Executor,
2539 Self::Interface => diagnostic_code::ErrorOrigin::Interface,
2540 }
2541 }
2542}
2543
2544impl fmt::Debug for ErrorOrigin {
2545 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2546 write!(f, "{}", *self as u8)
2547 }
2548}