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 #[cold]
1089 #[inline(never)]
1090 pub(crate) fn store_unsupported() -> Self {
1091 Self::new(ErrorClass::Unsupported, ErrorOrigin::Store)
1092 }
1093
1094 pub(crate) fn schema_application_conflict() -> Self {
1096 Self::new(ErrorClass::Conflict, ErrorOrigin::Store)
1097 }
1098
1099 #[cfg(any(test, feature = "query"))]
1101 pub(crate) fn schema_ddl_publication_race_lost(_entity_path: &str) -> Self {
1102 Self {
1103 class: ErrorClass::Unsupported,
1104 origin: ErrorOrigin::Store,
1105 detail: Some(ErrorDetail::Store(StoreError::SchemaDdlPublicationRaceLost)),
1106 }
1107 }
1108
1109 #[cfg(feature = "sql")]
1111 pub(crate) fn schema_ddl_rewrite_requires_migration(_entity_path: &str) -> Self {
1112 Self {
1113 class: ErrorClass::Unsupported,
1114 origin: ErrorOrigin::Store,
1115 detail: Some(ErrorDetail::Store(
1116 StoreError::SchemaDdlRewriteRequiresMigration,
1117 )),
1118 }
1119 }
1120
1121 pub(crate) fn journal_mutation_revision_exhausted() -> Self {
1123 Self {
1124 class: ErrorClass::Unsupported,
1125 origin: ErrorOrigin::Store,
1126 detail: Some(ErrorDetail::Store(
1127 StoreError::JournalMutationRevisionExhausted,
1128 )),
1129 }
1130 }
1131
1132 pub(crate) fn schema_transition_budget_exceeded(
1134 resource: SchemaTransitionBudgetResource,
1135 ) -> Self {
1136 Self {
1137 class: ErrorClass::Unsupported,
1138 origin: ErrorOrigin::Store,
1139 detail: Some(ErrorDetail::Store(
1140 StoreError::SchemaTransitionBudgetExceeded { resource },
1141 )),
1142 }
1143 }
1144
1145 pub(crate) fn unsupported_entity_tag_in_data_store(
1147 _entity_tag: crate::types::EntityTag,
1148 ) -> Self {
1149 Self::store_unsupported()
1150 }
1151
1152 #[cfg(not(test))]
1154 pub(crate) fn commit_memory_id_registration_failed(_err: impl Sized) -> Self {
1155 Self::store_internal()
1156 }
1157
1158 pub(crate) fn index_unsupported() -> Self {
1160 Self::new(ErrorClass::Unsupported, ErrorOrigin::Index)
1161 }
1162
1163 pub(crate) fn index_component_exceeds_max_size() -> Self {
1165 Self::index_unsupported()
1166 }
1167
1168 pub(crate) fn serialize_unsupported() -> Self {
1170 Self::new(ErrorClass::Unsupported, ErrorOrigin::Serialize)
1171 }
1172
1173 #[cfg(any(test, feature = "query"))]
1175 pub(crate) fn cursor_invalid_continuation() -> Self {
1176 Self::new(ErrorClass::Unsupported, ErrorOrigin::Cursor)
1177 }
1178
1179 pub(crate) fn serialize_incompatible_persisted_format() -> Self {
1181 Self::new(
1182 ErrorClass::IncompatiblePersistedFormat,
1183 ErrorOrigin::Serialize,
1184 )
1185 }
1186
1187 #[cfg(feature = "sql")]
1190 pub(crate) fn query_unsupported_sql_feature(feature: diagnostic_code::SqlFeatureCode) -> Self {
1191 Self {
1192 class: ErrorClass::Unsupported,
1193 origin: ErrorOrigin::Query,
1194 detail: Some(ErrorDetail::Query(
1195 QueryErrorDetail::UnsupportedSqlFeature { feature },
1196 )),
1197 }
1198 }
1199
1200 #[cfg(feature = "sql")]
1203 pub(crate) fn query_sql_lowering(reason: diagnostic_code::SqlLoweringCode) -> Self {
1204 Self {
1205 class: ErrorClass::Unsupported,
1206 origin: ErrorOrigin::Query,
1207 detail: Some(ErrorDetail::Query(QueryErrorDetail::SqlLowering { reason })),
1208 }
1209 }
1210
1211 #[cfg(any(test, feature = "query"))]
1214 pub(crate) fn query_unsupported_projection(
1215 reason: diagnostic_code::QueryProjectionCode,
1216 ) -> Self {
1217 Self {
1218 class: ErrorClass::Unsupported,
1219 origin: ErrorOrigin::Query,
1220 detail: Some(ErrorDetail::Query(
1221 QueryErrorDetail::UnsupportedProjection { reason },
1222 )),
1223 }
1224 }
1225
1226 #[cfg(any(test, feature = "query"))]
1228 pub(crate) fn query_unknown_aggregate_target_field() -> Self {
1229 Self {
1230 class: ErrorClass::Unsupported,
1231 origin: ErrorOrigin::Query,
1232 detail: Some(ErrorDetail::Query(
1233 QueryErrorDetail::UnknownAggregateTargetField,
1234 )),
1235 }
1236 }
1237
1238 #[cfg(feature = "sql")]
1241 pub(crate) fn query_sql_surface_mismatch(
1242 mismatch: diagnostic_code::SqlSurfaceMismatchCode,
1243 ) -> Self {
1244 Self {
1245 class: ErrorClass::Unsupported,
1246 origin: ErrorOrigin::Query,
1247 detail: Some(ErrorDetail::Query(QueryErrorDetail::SqlSurfaceMismatch {
1248 mismatch,
1249 })),
1250 }
1251 }
1252
1253 pub(crate) fn query_sql_write_boundary(
1255 boundary: diagnostic_code::SqlWriteBoundaryCode,
1256 ) -> Self {
1257 Self {
1258 class: ErrorClass::Unsupported,
1259 origin: ErrorOrigin::Query,
1260 detail: Some(ErrorDetail::Query(QueryErrorDetail::SqlWriteBoundary {
1261 boundary,
1262 })),
1263 }
1264 }
1265
1266 pub fn store_not_found(_key: impl Sized) -> Self {
1267 Self {
1268 class: ErrorClass::NotFound,
1269 origin: ErrorOrigin::Store,
1270 detail: Some(ErrorDetail::Store(StoreError::NotFound)),
1271 }
1272 }
1273
1274 pub fn unsupported_entity_path(_path: impl Sized) -> Self {
1276 Self::store_unsupported()
1277 }
1278
1279 #[must_use]
1280 pub const fn is_not_found(&self) -> bool {
1281 matches!(self.detail, Some(ErrorDetail::Store(StoreError::NotFound)))
1282 }
1283
1284 #[cold]
1286 #[inline(never)]
1287 pub(crate) fn index_plan_corruption(origin: ErrorOrigin) -> Self {
1288 Self::new(ErrorClass::Corruption, origin)
1289 }
1290
1291 #[cold]
1293 #[inline(never)]
1294 pub(crate) fn index_plan_index_corruption() -> Self {
1295 Self::index_plan_corruption(ErrorOrigin::Index)
1296 }
1297
1298 #[cold]
1300 #[inline(never)]
1301 pub(crate) fn index_plan_store_corruption() -> Self {
1302 Self::index_plan_corruption(ErrorOrigin::Store)
1303 }
1304
1305 #[cold]
1307 #[inline(never)]
1308 pub(crate) fn index_plan_serialize_corruption() -> Self {
1309 Self::index_plan_corruption(ErrorOrigin::Serialize)
1310 }
1311
1312 #[cfg(test)]
1314 pub(crate) fn index_plan_invariant(origin: ErrorOrigin) -> Self {
1315 Self::new(ErrorClass::InvariantViolation, origin)
1316 }
1317
1318 #[cfg(test)]
1320 pub(crate) fn index_plan_store_invariant() -> Self {
1321 Self::index_plan_invariant(ErrorOrigin::Store)
1322 }
1323
1324 pub(crate) fn index_conflict() -> Self {
1330 Self::new(ErrorClass::Conflict, ErrorOrigin::Index)
1331 }
1332}
1333
1334impl From<diagnostic_code::QueryReadAdmissionCode> for InternalError {
1335 fn from(reason: diagnostic_code::QueryReadAdmissionCode) -> Self {
1336 Self {
1337 class: ErrorClass::Unsupported,
1338 origin: ErrorOrigin::Query,
1339 detail: Some(ErrorDetail::Query(QueryErrorDetail::QueryReadAdmission {
1340 reason,
1341 })),
1342 }
1343 }
1344}
1345
1346impl fmt::Debug for InternalError {
1347 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1348 fmt_compact_diagnostic(
1349 f,
1350 self.diagnostic_code(),
1351 self.detail
1352 .as_ref()
1353 .and_then(ErrorDetail::diagnostic_detail),
1354 )
1355 }
1356}
1357
1358impl fmt::Display for InternalError {
1359 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1360 f.write_str(self.message())
1361 }
1362}
1363
1364impl std::error::Error for InternalError {}
1365
1366#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq)]
1374pub enum ConstraintDiagnosticKind {
1375 Check,
1377
1378 NotNull,
1380
1381 Relation,
1383
1384 TargetedRule,
1386
1387 Unique,
1389}
1390
1391impl ConstraintDiagnosticKind {
1392 #[must_use]
1394 pub const fn as_str(self) -> &'static str {
1395 match self {
1396 Self::Check => "check",
1397 Self::NotNull => "not_null",
1398 Self::Relation => "relation",
1399 Self::TargetedRule => "targeted_rule",
1400 Self::Unique => "unique",
1401 }
1402 }
1403}
1404
1405#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq)]
1414pub enum ConstraintValuePathComponent {
1415 RootField { field_id: u32 },
1417
1418 RecordMember {
1420 composite_type_id: u32,
1421 member_id: u32,
1422 },
1423
1424 TupleElement {
1426 composite_type_id: u32,
1427 ordinal: u32,
1428 },
1429
1430 Newtype { composite_type_id: u32 },
1432
1433 EnumVariant { enum_type_id: u32, variant_id: u32 },
1435
1436 ListElement { index: u32 },
1438
1439 SetElement { index: u32 },
1441
1442 MapEntryKey { index: u32 },
1444
1445 MapEntryValue { index: u32 },
1447}
1448
1449impl fmt::Display for ConstraintValuePathComponent {
1450 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1451 match self {
1452 Self::RootField { field_id } => write!(f, "field#{field_id}"),
1453 Self::RecordMember {
1454 composite_type_id,
1455 member_id,
1456 } => write!(f, "record#{composite_type_id}.member#{member_id}"),
1457 Self::TupleElement {
1458 composite_type_id,
1459 ordinal,
1460 } => write!(f, "tuple#{composite_type_id}[{ordinal}]"),
1461 Self::Newtype { composite_type_id } => write!(f, "newtype#{composite_type_id}"),
1462 Self::EnumVariant {
1463 enum_type_id,
1464 variant_id,
1465 } => write!(f, "enum#{enum_type_id}.variant#{variant_id}"),
1466 Self::ListElement { index } => write!(f, "list[{index}]"),
1467 Self::SetElement { index } => write!(f, "set[{index}]"),
1468 Self::MapEntryKey { index } => write!(f, "map[{index}].key"),
1469 Self::MapEntryValue { index } => write!(f, "map[{index}].value"),
1470 }
1471 }
1472}
1473
1474#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
1481pub struct ConstraintValuePath {
1482 components: Vec<ConstraintValuePathComponent>,
1483}
1484
1485impl ConstraintValuePath {
1486 #[must_use]
1488 pub(crate) const fn new(components: Vec<ConstraintValuePathComponent>) -> Self {
1489 Self { components }
1490 }
1491
1492 #[must_use]
1494 pub const fn components(&self) -> &[ConstraintValuePathComponent] {
1495 self.components.as_slice()
1496 }
1497}
1498
1499impl fmt::Display for ConstraintValuePath {
1500 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1501 for (ordinal, component) in self.components.iter().enumerate() {
1502 if ordinal != 0 {
1503 f.write_str("/")?;
1504 }
1505 component.fmt(f)?;
1506 }
1507 Ok(())
1508 }
1509}
1510
1511#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq)]
1519pub enum ConstraintDiagnosticContext {
1520 Integrity,
1522
1523 MigrationValidation,
1525
1526 WriteAdmission,
1528}
1529
1530impl ConstraintDiagnosticContext {
1531 #[must_use]
1533 pub const fn as_str(self) -> &'static str {
1534 match self {
1535 Self::Integrity => "integrity",
1536 Self::MigrationValidation => "migration_validation",
1537 Self::WriteAdmission => "write_admission",
1538 }
1539 }
1540}
1541
1542#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
1551pub struct ConstraintDiagnostic {
1552 constraint_id: u32,
1553 constraint_name: String,
1554 constraint_kind: ConstraintDiagnosticKind,
1555 entity: String,
1556 primary_key: Option<Vec<u8>>,
1557 field_paths: Vec<String>,
1558 value_path: Option<Box<ConstraintValuePath>>,
1559 context: ConstraintDiagnosticContext,
1560 error_code: u16,
1561}
1562
1563impl ConstraintDiagnostic {
1564 #[must_use]
1566 pub(crate) const fn write_violation(
1567 constraint_id: u32,
1568 constraint_name: String,
1569 constraint_kind: ConstraintDiagnosticKind,
1570 entity: String,
1571 primary_key: Option<Vec<u8>>,
1572 field_paths: Vec<String>,
1573 ) -> Self {
1574 Self {
1575 constraint_id,
1576 constraint_name,
1577 constraint_kind,
1578 entity,
1579 primary_key,
1580 field_paths,
1581 value_path: None,
1582 context: ConstraintDiagnosticContext::WriteAdmission,
1583 error_code: diagnostic_code::ErrorCode::RUNTIME_BOUNDARY_CONSTRAINT_VIOLATION.raw(),
1584 }
1585 }
1586
1587 #[must_use]
1589 pub(crate) fn write_targeted_rule_violation(
1590 constraint_id: u32,
1591 constraint_name: String,
1592 entity: String,
1593 primary_key: Option<Vec<u8>>,
1594 field_paths: Vec<String>,
1595 value_path: ConstraintValuePath,
1596 ) -> Self {
1597 Self {
1598 constraint_id,
1599 constraint_name,
1600 constraint_kind: ConstraintDiagnosticKind::TargetedRule,
1601 entity,
1602 primary_key,
1603 field_paths,
1604 value_path: Some(Box::new(value_path)),
1605 context: ConstraintDiagnosticContext::WriteAdmission,
1606 error_code: diagnostic_code::ErrorCode::RUNTIME_BOUNDARY_CONSTRAINT_VIOLATION.raw(),
1607 }
1608 }
1609
1610 #[must_use]
1612 pub(crate) const fn write_activation_blocked(
1613 constraint_id: u32,
1614 constraint_name: String,
1615 constraint_kind: ConstraintDiagnosticKind,
1616 entity: String,
1617 primary_key: Option<Vec<u8>>,
1618 field_paths: Vec<String>,
1619 ) -> Self {
1620 Self {
1621 constraint_id,
1622 constraint_name,
1623 constraint_kind,
1624 entity,
1625 primary_key,
1626 field_paths,
1627 value_path: None,
1628 context: ConstraintDiagnosticContext::WriteAdmission,
1629 error_code:
1630 diagnostic_code::ErrorCode::RUNTIME_BOUNDARY_CONSTRAINT_ACTIVATION_WRITE_BLOCKED
1631 .raw(),
1632 }
1633 }
1634
1635 #[must_use]
1637 pub(crate) const fn migration_validation(
1638 constraint_id: u32,
1639 constraint_name: String,
1640 constraint_kind: ConstraintDiagnosticKind,
1641 entity: String,
1642 primary_key: Vec<u8>,
1643 field_paths: Vec<String>,
1644 error_code: u16,
1645 ) -> Self {
1646 Self {
1647 constraint_id,
1648 constraint_name,
1649 constraint_kind,
1650 entity,
1651 primary_key: Some(primary_key),
1652 field_paths,
1653 value_path: None,
1654 context: ConstraintDiagnosticContext::MigrationValidation,
1655 error_code,
1656 }
1657 }
1658
1659 #[must_use]
1661 pub(crate) fn migration_targeted_rule_validation(
1662 constraint_id: u32,
1663 constraint_name: String,
1664 entity: String,
1665 primary_key: Vec<u8>,
1666 field_paths: Vec<String>,
1667 value_path: ConstraintValuePath,
1668 error_code: u16,
1669 ) -> Self {
1670 Self {
1671 constraint_id,
1672 constraint_name,
1673 constraint_kind: ConstraintDiagnosticKind::TargetedRule,
1674 entity,
1675 primary_key: Some(primary_key),
1676 field_paths,
1677 value_path: Some(Box::new(value_path)),
1678 context: ConstraintDiagnosticContext::MigrationValidation,
1679 error_code,
1680 }
1681 }
1682
1683 #[must_use]
1685 pub const fn constraint_id(&self) -> u32 {
1686 self.constraint_id
1687 }
1688
1689 #[must_use]
1691 pub const fn constraint_name(&self) -> &str {
1692 self.constraint_name.as_str()
1693 }
1694
1695 #[must_use]
1697 pub const fn constraint_kind(&self) -> ConstraintDiagnosticKind {
1698 self.constraint_kind
1699 }
1700
1701 #[must_use]
1703 pub const fn entity(&self) -> &str {
1704 self.entity.as_str()
1705 }
1706
1707 #[must_use]
1709 pub fn primary_key(&self) -> Option<&[u8]> {
1710 self.primary_key.as_deref()
1711 }
1712
1713 #[must_use]
1715 pub const fn field_paths(&self) -> &[String] {
1716 self.field_paths.as_slice()
1717 }
1718
1719 #[must_use]
1721 pub fn value_path(&self) -> Option<&ConstraintValuePath> {
1722 self.value_path.as_deref()
1723 }
1724
1725 #[must_use]
1727 pub const fn context(&self) -> ConstraintDiagnosticContext {
1728 self.context
1729 }
1730
1731 #[must_use]
1733 pub const fn error_code(&self) -> diagnostic_code::ErrorCode {
1734 diagnostic_code::ErrorCode::from_raw(self.error_code)
1735 }
1736
1737 #[must_use]
1739 pub const fn error_class(&self) -> diagnostic_code::ErrorClass {
1740 self.error_code().class()
1741 }
1742}
1743
1744pub enum ErrorDetail {
1752 Executor(ExecutorErrorDetail),
1754 Store(StoreError),
1755 Query(QueryErrorDetail),
1756 Recovery(RecoveryErrorDetail),
1757 Serialize(SerializeErrorDetail),
1759 }
1762
1763pub enum ExecutorErrorDetail {
1765 MutationRequiredFieldMissing,
1767 MutationManagedTimestampRegression,
1769 MutationDatabaseOwnedFieldExplicit,
1771 ConstraintViolation {
1773 diagnostic: Box<ConstraintDiagnostic>,
1774 },
1775 AcceptedRowConstraintProgramCorrupt,
1777 ConstraintActivationWriteBlocked {
1779 diagnostic: Box<ConstraintDiagnostic>,
1780 },
1781}
1782
1783impl ExecutorErrorDetail {
1784 #[must_use]
1786 pub fn constraint_diagnostic(&self) -> Option<&ConstraintDiagnostic> {
1787 match self {
1788 Self::ConstraintActivationWriteBlocked { diagnostic }
1789 | Self::ConstraintViolation { diagnostic } => Some(diagnostic.as_ref()),
1790 Self::MutationRequiredFieldMissing
1791 | Self::MutationManagedTimestampRegression
1792 | Self::MutationDatabaseOwnedFieldExplicit
1793 | Self::AcceptedRowConstraintProgramCorrupt => None,
1794 }
1795 }
1796}
1797
1798pub enum SerializeErrorDetail {
1800 PersistedRowLayoutOutsideAcceptedWindow,
1802
1803 PersistedRowSlotCountMismatch,
1805}
1806
1807pub enum RecoveryErrorDetail {
1814 UnsupportedFormatVersion { found: Option<u16>, required: u16 },
1815
1816 MalformedFormatMarker { reason: RecoveryFormatMarkerError },
1817}
1818
1819#[derive(Clone, Copy, Eq, PartialEq)]
1821pub enum RecoveryFormatMarkerError {
1822 Magic,
1823 Checksum,
1824 State,
1825}
1826
1827pub enum StoreError {
1835 NotFound,
1836
1837 Corrupt,
1838
1839 InvariantViolation,
1840
1841 SchemaDdlPublicationRaceLost,
1842
1843 SchemaDdlRewriteRequiresMigration,
1844
1845 SchemaRowLayoutVersionExhausted,
1846
1847 JournalMutationRevisionExhausted,
1848
1849 SchemaTransitionBudgetExceeded {
1850 resource: SchemaTransitionBudgetResource,
1851 },
1852
1853 SchemaGeneratedFieldAfterDdlField,
1855
1856 SchemaGeneratedConstraintActivationStale,
1858}
1859
1860pub enum QueryErrorDetail {
1867 NumericOverflow,
1868
1869 NumericNotRepresentable,
1870
1871 UnsupportedSqlFeature {
1872 feature: diagnostic_code::SqlFeatureCode,
1873 },
1874
1875 SqlLowering {
1876 reason: diagnostic_code::SqlLoweringCode,
1877 },
1878
1879 UnsupportedProjection {
1880 reason: diagnostic_code::QueryProjectionCode,
1881 },
1882
1883 UnknownAggregateTargetField,
1884
1885 ResultShapeMismatch {
1886 reason: diagnostic_code::QueryResultShapeCode,
1887 },
1888
1889 QueryReadAdmission {
1890 reason: diagnostic_code::QueryReadAdmissionCode,
1891 },
1892
1893 SqlSurfaceMismatch {
1894 mismatch: diagnostic_code::SqlSurfaceMismatchCode,
1895 },
1896
1897 SqlWriteBoundary {
1898 boundary: diagnostic_code::SqlWriteBoundaryCode,
1899 },
1900
1901 SchemaDdlAdmission {
1902 error: SchemaDdlAdmissionError,
1903 },
1904
1905 StaleSchemaRevision,
1906}
1907
1908impl fmt::Display for QueryErrorDetail {
1909 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1910 f.write_str(COMPACT_QUERY_DIAGNOSTIC_MESSAGE)
1911 }
1912}
1913
1914impl std::error::Error for QueryErrorDetail {}
1915
1916#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1924pub enum SchemaTransitionBudgetResource {
1925 DeletionKeys,
1927 ProjectionEntries,
1929 ProjectionWorkUnits,
1931 SourceRows,
1933 SourceRowBytes,
1935 StagedRawBytes,
1937}
1938
1939#[derive(Clone, Copy, Eq, PartialEq)]
1948pub enum SchemaDdlAdmissionError {
1949 MissingExpectedSchemaVersion,
1950
1951 MissingNextSchemaVersion,
1952
1953 StaleExpectedSchemaVersion,
1954
1955 InvalidExpectedSchemaVersion,
1956
1957 InvalidNextSchemaVersion,
1958
1959 AcceptedSchemaChangeWithoutVersionBump,
1960
1961 EmptyVersionBump,
1962
1963 VersionGap,
1964
1965 VersionRollback,
1966
1967 FingerprintMethodMismatch,
1968
1969 UnsupportedTransitionClass,
1970
1971 PhysicalRunnerMissing,
1972
1973 ValidationFailed,
1974
1975 PublicationRaceLost,
1976
1977 InvalidAddColumnDefault,
1978
1979 InvalidAlterColumnDefault,
1980
1981 RowLayoutVersionExhausted,
1982
1983 GeneratedIndexDropRejected,
1984
1985 SchemaRewriteRequiresMigration,
1986
1987 SchemaTransitionBudgetExceeded {
1988 resource: SchemaTransitionBudgetResource,
1989 },
1990
1991 GeneratedFieldDefaultChangeRejected,
1992
1993 GeneratedFieldNullabilityChangeRejected,
1994}
1995
1996impl fmt::Display for SchemaDdlAdmissionError {
1997 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1998 f.write_str(COMPACT_QUERY_DIAGNOSTIC_MESSAGE)
1999 }
2000}
2001
2002impl std::error::Error for SchemaDdlAdmissionError {}
2003
2004impl fmt::Debug for ErrorDetail {
2005 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2006 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2007 }
2008}
2009
2010impl fmt::Debug for ExecutorErrorDetail {
2011 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2012 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2013 }
2014}
2015
2016impl fmt::Debug for StoreError {
2017 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2018 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2019 }
2020}
2021
2022impl fmt::Debug for QueryErrorDetail {
2023 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2024 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2025 }
2026}
2027
2028impl fmt::Debug for RecoveryErrorDetail {
2029 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2030 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2031 }
2032}
2033
2034impl fmt::Debug for SerializeErrorDetail {
2035 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2036 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2037 }
2038}
2039
2040impl fmt::Debug for RecoveryFormatMarkerError {
2041 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2042 fmt_compact_diagnostic(
2043 f,
2044 diagnostic_code::DiagnosticCode::RuntimeCorruption,
2045 Some(diagnostic_code::DiagnosticDetail::RuntimeKind {
2046 kind: diagnostic_code::RuntimeErrorKind::Corruption,
2047 }),
2048 )
2049 }
2050}
2051
2052impl fmt::Debug for SchemaDdlAdmissionError {
2053 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2054 fmt_compact_diagnostic(
2055 f,
2056 diagnostic_code::DiagnosticCode::SchemaDdlAdmission,
2057 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2058 reason: self.diagnostic_code(),
2059 }),
2060 )
2061 }
2062}
2063
2064fn fmt_compact_diagnostic(
2065 f: &mut fmt::Formatter<'_>,
2066 code: diagnostic_code::DiagnosticCode,
2067 detail: Option<diagnostic_code::DiagnosticDetail>,
2068) -> fmt::Result {
2069 write!(
2070 f,
2071 "{}",
2072 diagnostic_code::ErrorCode::from_parts(code, detail).raw()
2073 )
2074}
2075
2076impl ErrorDetail {
2077 #[must_use]
2079 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2080 match self {
2081 Self::Executor(error) => error.diagnostic_code(),
2082 Self::Store(error) => error.diagnostic_code(),
2083 Self::Query(error) => error.diagnostic_code(),
2084 Self::Recovery(error) => error.diagnostic_code(),
2085 Self::Serialize(error) => error.diagnostic_code(),
2086 }
2087 }
2088
2089 #[must_use]
2091 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2092 match self {
2093 Self::Executor(error) => error.diagnostic_detail(),
2094 Self::Store(error) => error.diagnostic_detail(),
2095 Self::Query(error) => error.diagnostic_detail(),
2096 Self::Recovery(error) => error.diagnostic_detail(),
2097 Self::Serialize(error) => error.diagnostic_detail(),
2098 }
2099 }
2100}
2101
2102impl ExecutorErrorDetail {
2103 #[must_use]
2105 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2106 match self {
2107 Self::MutationRequiredFieldMissing | Self::MutationDatabaseOwnedFieldExplicit => {
2108 diagnostic_code::DiagnosticCode::RuntimeUnsupported
2109 }
2110 Self::MutationManagedTimestampRegression => {
2111 diagnostic_code::DiagnosticCode::RuntimeInvariantViolation
2112 }
2113 Self::ConstraintViolation { diagnostic }
2114 | Self::ConstraintActivationWriteBlocked { diagnostic } => {
2115 diagnostic.error_code().diagnostic_code()
2116 }
2117 Self::AcceptedRowConstraintProgramCorrupt => {
2118 diagnostic_code::DiagnosticCode::RuntimeCorruption
2119 }
2120 }
2121 }
2122
2123 #[must_use]
2125 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2126 match self {
2127 Self::MutationRequiredFieldMissing => {
2128 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2129 boundary: diagnostic_code::RuntimeBoundaryCode::MutationRequiredFieldMissing,
2130 })
2131 }
2132 Self::MutationDatabaseOwnedFieldExplicit => {
2133 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2134 boundary:
2135 diagnostic_code::RuntimeBoundaryCode::MutationDatabaseOwnedFieldExplicit,
2136 })
2137 }
2138 Self::MutationManagedTimestampRegression => {
2139 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2140 boundary:
2141 diagnostic_code::RuntimeBoundaryCode::MutationManagedTimestampRegression,
2142 })
2143 }
2144 Self::ConstraintViolation { diagnostic }
2145 | Self::ConstraintActivationWriteBlocked { diagnostic } => {
2146 diagnostic.error_code().diagnostic_detail()
2147 }
2148 Self::AcceptedRowConstraintProgramCorrupt => {
2149 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2150 boundary:
2151 diagnostic_code::RuntimeBoundaryCode::AcceptedRowConstraintProgramCorrupt,
2152 })
2153 }
2154 }
2155 }
2156}
2157
2158impl RecoveryErrorDetail {
2159 #[must_use]
2161 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2162 match self {
2163 Self::UnsupportedFormatVersion { .. } => {
2164 diagnostic_code::DiagnosticCode::RuntimeIncompatiblePersistedFormat
2165 }
2166 Self::MalformedFormatMarker { .. } => {
2167 diagnostic_code::DiagnosticCode::RuntimeCorruption
2168 }
2169 }
2170 }
2171
2172 #[must_use]
2174 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2175 let kind = match self {
2176 Self::UnsupportedFormatVersion { .. } => {
2177 diagnostic_code::RuntimeErrorKind::IncompatiblePersistedFormat
2178 }
2179 Self::MalformedFormatMarker { .. } => diagnostic_code::RuntimeErrorKind::Corruption,
2180 };
2181
2182 Some(diagnostic_code::DiagnosticDetail::RuntimeKind { kind })
2183 }
2184}
2185
2186impl SerializeErrorDetail {
2187 #[must_use]
2189 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2190 match self {
2191 Self::PersistedRowLayoutOutsideAcceptedWindow | Self::PersistedRowSlotCountMismatch => {
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 boundary = match self {
2201 Self::PersistedRowLayoutOutsideAcceptedWindow => {
2202 diagnostic_code::RuntimeBoundaryCode::PersistedRowLayoutOutsideAcceptedWindow
2203 }
2204 Self::PersistedRowSlotCountMismatch => {
2205 diagnostic_code::RuntimeBoundaryCode::PersistedRowSlotCountMismatch
2206 }
2207 };
2208
2209 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary { boundary })
2210 }
2211}
2212
2213impl StoreError {
2214 #[must_use]
2216 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2217 match self {
2218 Self::NotFound => diagnostic_code::DiagnosticCode::StoreNotFound,
2219 Self::Corrupt => diagnostic_code::DiagnosticCode::StoreCorruption,
2220 Self::InvariantViolation => diagnostic_code::DiagnosticCode::StoreInvariantViolation,
2221 Self::SchemaDdlPublicationRaceLost
2222 | Self::SchemaDdlRewriteRequiresMigration
2223 | Self::SchemaRowLayoutVersionExhausted
2224 | Self::SchemaTransitionBudgetExceeded { .. } => {
2225 diagnostic_code::DiagnosticCode::SchemaDdlAdmission
2226 }
2227 Self::JournalMutationRevisionExhausted | Self::SchemaGeneratedFieldAfterDdlField => {
2228 diagnostic_code::DiagnosticCode::RuntimeUnsupported
2229 }
2230 Self::SchemaGeneratedConstraintActivationStale => {
2231 diagnostic_code::DiagnosticCode::RuntimeConflict
2232 }
2233 }
2234 }
2235
2236 #[must_use]
2238 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2239 match self {
2240 Self::SchemaDdlPublicationRaceLost => {
2241 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2242 reason: diagnostic_code::SchemaDdlAdmissionCode::PublicationRaceLost,
2243 })
2244 }
2245 Self::SchemaDdlRewriteRequiresMigration => {
2246 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2247 reason: diagnostic_code::SchemaDdlAdmissionCode::SchemaRewriteRequiresMigration,
2248 })
2249 }
2250 Self::SchemaRowLayoutVersionExhausted => {
2251 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2252 reason: diagnostic_code::SchemaDdlAdmissionCode::RowLayoutVersionExhausted,
2253 })
2254 }
2255 Self::JournalMutationRevisionExhausted => {
2256 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2257 boundary:
2258 diagnostic_code::RuntimeBoundaryCode::JournalMutationRevisionExhausted,
2259 })
2260 }
2261 Self::SchemaTransitionBudgetExceeded { .. } => {
2262 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2263 reason: diagnostic_code::SchemaDdlAdmissionCode::SchemaTransitionBudgetExceeded,
2264 })
2265 }
2266 Self::SchemaGeneratedFieldAfterDdlField => {
2267 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2268 boundary: diagnostic_code::RuntimeBoundaryCode::GeneratedFieldAfterDdlField,
2269 })
2270 }
2271 Self::SchemaGeneratedConstraintActivationStale => {
2272 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2273 boundary:
2274 diagnostic_code::RuntimeBoundaryCode::GeneratedConstraintActivationStale,
2275 })
2276 }
2277 Self::NotFound | Self::Corrupt | Self::InvariantViolation => None,
2278 }
2279 }
2280}
2281
2282impl QueryErrorDetail {
2283 #[must_use]
2285 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2286 match self {
2287 Self::NumericOverflow => diagnostic_code::DiagnosticCode::QueryNumericOverflow,
2288 Self::NumericNotRepresentable => {
2289 diagnostic_code::DiagnosticCode::QueryNumericNotRepresentable
2290 }
2291 Self::UnsupportedSqlFeature { .. } => {
2292 diagnostic_code::DiagnosticCode::QueryUnsupportedSqlFeature
2293 }
2294 Self::SqlLowering { .. } => diagnostic_code::DiagnosticCode::QueryUnsupportedSqlFeature,
2295 Self::UnsupportedProjection { .. } => {
2296 diagnostic_code::DiagnosticCode::QueryUnsupportedProjection
2297 }
2298 Self::UnknownAggregateTargetField => {
2299 diagnostic_code::DiagnosticCode::QueryUnknownAggregateTargetField
2300 }
2301 Self::ResultShapeMismatch { .. } => {
2302 diagnostic_code::DiagnosticCode::QueryResultShapeMismatch
2303 }
2304 Self::QueryReadAdmission { .. } => diagnostic_code::DiagnosticCode::QueryReadAdmission,
2305 Self::SqlSurfaceMismatch { .. } => {
2306 diagnostic_code::DiagnosticCode::QuerySqlSurfaceMismatch
2307 }
2308 Self::SqlWriteBoundary { .. } => diagnostic_code::DiagnosticCode::QuerySqlWriteBoundary,
2309 Self::SchemaDdlAdmission { .. } => diagnostic_code::DiagnosticCode::SchemaDdlAdmission,
2310 Self::StaleSchemaRevision => diagnostic_code::DiagnosticCode::RuntimeConflict,
2311 }
2312 }
2313
2314 #[must_use]
2316 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2317 match self {
2318 Self::UnsupportedSqlFeature { feature } => {
2319 Some(diagnostic_code::DiagnosticDetail::UnsupportedSqlFeature { feature: *feature })
2320 }
2321 Self::SqlLowering { reason } => {
2322 Some(diagnostic_code::DiagnosticDetail::SqlLowering { reason: *reason })
2323 }
2324 Self::UnsupportedProjection { reason } => {
2325 Some(diagnostic_code::DiagnosticDetail::QueryProjection { reason: *reason })
2326 }
2327 Self::ResultShapeMismatch { reason } => {
2328 Some(diagnostic_code::DiagnosticDetail::QueryResultShape { reason: *reason })
2329 }
2330 Self::QueryReadAdmission { reason } => {
2331 Some(diagnostic_code::DiagnosticDetail::QueryReadAdmission { reason: *reason })
2332 }
2333 Self::SqlSurfaceMismatch { mismatch } => {
2334 Some(diagnostic_code::DiagnosticDetail::SqlSurfaceMismatch {
2335 mismatch: *mismatch,
2336 })
2337 }
2338 Self::SqlWriteBoundary { boundary } => {
2339 Some(diagnostic_code::DiagnosticDetail::SqlWriteBoundary {
2340 boundary: *boundary,
2341 })
2342 }
2343 Self::SchemaDdlAdmission { error } => {
2344 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2345 reason: error.diagnostic_code(),
2346 })
2347 }
2348 Self::NumericOverflow
2349 | Self::NumericNotRepresentable
2350 | Self::UnknownAggregateTargetField
2351 | Self::StaleSchemaRevision => None,
2352 }
2353 }
2354}
2355
2356impl SchemaDdlAdmissionError {
2357 #[must_use]
2359 pub const fn diagnostic_code(&self) -> diagnostic_code::SchemaDdlAdmissionCode {
2360 match self {
2361 Self::MissingExpectedSchemaVersion => {
2362 diagnostic_code::SchemaDdlAdmissionCode::MissingExpectedSchemaVersion
2363 }
2364 Self::MissingNextSchemaVersion => {
2365 diagnostic_code::SchemaDdlAdmissionCode::MissingNextSchemaVersion
2366 }
2367 Self::StaleExpectedSchemaVersion => {
2368 diagnostic_code::SchemaDdlAdmissionCode::StaleExpectedSchemaVersion
2369 }
2370 Self::InvalidExpectedSchemaVersion => {
2371 diagnostic_code::SchemaDdlAdmissionCode::InvalidExpectedSchemaVersion
2372 }
2373 Self::InvalidNextSchemaVersion => {
2374 diagnostic_code::SchemaDdlAdmissionCode::InvalidNextSchemaVersion
2375 }
2376 Self::AcceptedSchemaChangeWithoutVersionBump => {
2377 diagnostic_code::SchemaDdlAdmissionCode::AcceptedSchemaChangeWithoutVersionBump
2378 }
2379 Self::EmptyVersionBump => diagnostic_code::SchemaDdlAdmissionCode::EmptyVersionBump,
2380 Self::VersionGap => diagnostic_code::SchemaDdlAdmissionCode::VersionGap,
2381 Self::VersionRollback => diagnostic_code::SchemaDdlAdmissionCode::VersionRollback,
2382 Self::FingerprintMethodMismatch => {
2383 diagnostic_code::SchemaDdlAdmissionCode::FingerprintMethodMismatch
2384 }
2385 Self::UnsupportedTransitionClass => {
2386 diagnostic_code::SchemaDdlAdmissionCode::UnsupportedTransitionClass
2387 }
2388 Self::PhysicalRunnerMissing => {
2389 diagnostic_code::SchemaDdlAdmissionCode::PhysicalRunnerMissing
2390 }
2391 Self::ValidationFailed => diagnostic_code::SchemaDdlAdmissionCode::ValidationFailed,
2392 Self::PublicationRaceLost => {
2393 diagnostic_code::SchemaDdlAdmissionCode::PublicationRaceLost
2394 }
2395 Self::InvalidAddColumnDefault => {
2396 diagnostic_code::SchemaDdlAdmissionCode::InvalidAddColumnDefault
2397 }
2398 Self::InvalidAlterColumnDefault => {
2399 diagnostic_code::SchemaDdlAdmissionCode::InvalidAlterColumnDefault
2400 }
2401 Self::GeneratedIndexDropRejected => {
2402 diagnostic_code::SchemaDdlAdmissionCode::GeneratedIndexDropRejected
2403 }
2404 Self::SchemaRewriteRequiresMigration => {
2405 diagnostic_code::SchemaDdlAdmissionCode::SchemaRewriteRequiresMigration
2406 }
2407 Self::SchemaTransitionBudgetExceeded { .. } => {
2408 diagnostic_code::SchemaDdlAdmissionCode::SchemaTransitionBudgetExceeded
2409 }
2410 Self::GeneratedFieldDefaultChangeRejected => {
2411 diagnostic_code::SchemaDdlAdmissionCode::GeneratedFieldDefaultChangeRejected
2412 }
2413 Self::GeneratedFieldNullabilityChangeRejected => {
2414 diagnostic_code::SchemaDdlAdmissionCode::GeneratedFieldNullabilityChangeRejected
2415 }
2416 Self::RowLayoutVersionExhausted => {
2417 diagnostic_code::SchemaDdlAdmissionCode::RowLayoutVersionExhausted
2418 }
2419 }
2420 }
2421}
2422
2423#[repr(u8)]
2430#[derive(Clone, Copy, Eq, PartialEq)]
2431pub enum ErrorClass {
2432 Corruption,
2433 IncompatiblePersistedFormat,
2434 NotFound,
2435 Internal,
2436 Conflict,
2437 Unsupported,
2438 InvariantViolation,
2439}
2440
2441impl ErrorClass {
2442 #[must_use]
2444 pub const fn diagnostic_code(self, origin: ErrorOrigin) -> diagnostic_code::DiagnosticCode {
2445 match self {
2446 Self::Corruption if matches!(origin, ErrorOrigin::Store) => {
2447 diagnostic_code::DiagnosticCode::StoreCorruption
2448 }
2449 Self::Corruption => diagnostic_code::DiagnosticCode::RuntimeCorruption,
2450 Self::IncompatiblePersistedFormat => {
2451 diagnostic_code::DiagnosticCode::RuntimeIncompatiblePersistedFormat
2452 }
2453 Self::NotFound if matches!(origin, ErrorOrigin::Store) => {
2454 diagnostic_code::DiagnosticCode::StoreNotFound
2455 }
2456 Self::NotFound => diagnostic_code::DiagnosticCode::RuntimeNotFound,
2457 Self::Internal => diagnostic_code::DiagnosticCode::RuntimeInternal,
2458 Self::Conflict => diagnostic_code::DiagnosticCode::RuntimeConflict,
2459 Self::Unsupported if matches!(origin, ErrorOrigin::Cursor) => {
2460 diagnostic_code::DiagnosticCode::QueryInvalidContinuationCursor
2461 }
2462 Self::Unsupported => diagnostic_code::DiagnosticCode::RuntimeUnsupported,
2463 Self::InvariantViolation if matches!(origin, ErrorOrigin::Store) => {
2464 diagnostic_code::DiagnosticCode::StoreInvariantViolation
2465 }
2466 Self::InvariantViolation => diagnostic_code::DiagnosticCode::RuntimeInvariantViolation,
2467 }
2468 }
2469}
2470
2471impl fmt::Debug for ErrorClass {
2472 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2473 write!(f, "{}", *self as u8)
2474 }
2475}
2476
2477#[repr(u8)]
2484#[derive(Clone, Copy, Eq, PartialEq)]
2485pub enum ErrorOrigin {
2486 Serialize,
2487 Store,
2488 Index,
2489 Identity,
2490 Query,
2491 Planner,
2492 Cursor,
2493 Recovery,
2494 Response,
2495 Executor,
2496 Interface,
2497}
2498
2499impl ErrorOrigin {
2500 #[must_use]
2502 pub const fn diagnostic_origin(self) -> diagnostic_code::ErrorOrigin {
2503 match self {
2504 Self::Serialize => diagnostic_code::ErrorOrigin::Serialize,
2505 Self::Store => diagnostic_code::ErrorOrigin::Store,
2506 Self::Index => diagnostic_code::ErrorOrigin::Index,
2507 Self::Identity => diagnostic_code::ErrorOrigin::Identity,
2508 Self::Query => diagnostic_code::ErrorOrigin::Query,
2509 Self::Planner => diagnostic_code::ErrorOrigin::Planner,
2510 Self::Cursor => diagnostic_code::ErrorOrigin::Cursor,
2511 Self::Recovery => diagnostic_code::ErrorOrigin::Recovery,
2512 Self::Response => diagnostic_code::ErrorOrigin::Response,
2513 Self::Executor => diagnostic_code::ErrorOrigin::Executor,
2514 Self::Interface => diagnostic_code::ErrorOrigin::Interface,
2515 }
2516 }
2517}
2518
2519impl fmt::Debug for ErrorOrigin {
2520 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2521 write!(f, "{}", *self as u8)
2522 }
2523}