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 pub(crate) fn planner_executor_invariant() -> Self {
290 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Planner)
291 }
292
293 #[cold]
296 #[inline(never)]
297 pub(crate) fn query_executor_invariant() -> Self {
298 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Query)
299 }
300
301 #[cold]
304 #[inline(never)]
305 pub(crate) fn cursor_executor_invariant() -> Self {
306 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Cursor)
307 }
308
309 #[cold]
311 #[inline(never)]
312 pub(crate) fn executor_invariant() -> Self {
313 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Executor)
314 }
315
316 #[cold]
318 #[inline(never)]
319 pub(crate) fn executor_internal() -> Self {
320 Self::new(ErrorClass::Internal, ErrorOrigin::Executor)
321 }
322
323 #[cold]
325 #[inline(never)]
326 pub(crate) fn executor_unsupported() -> Self {
327 Self::new(ErrorClass::Unsupported, ErrorOrigin::Executor)
328 }
329
330 pub(crate) fn mutation_database_owned_field_explicit(
332 _entity_path: &str,
333 _field_name: &str,
334 ) -> Self {
335 Self {
336 class: ErrorClass::Unsupported,
337 origin: ErrorOrigin::Executor,
338 detail: Some(ErrorDetail::Executor(
339 ExecutorErrorDetail::MutationDatabaseOwnedFieldExplicit,
340 )),
341 }
342 }
343
344 #[must_use]
346 pub fn mutation_required_field_missing(_entity_path: &str, _field_names: &str) -> Self {
347 Self {
348 class: ErrorClass::Unsupported,
349 origin: ErrorOrigin::Executor,
350 detail: Some(ErrorDetail::Executor(
351 ExecutorErrorDetail::MutationRequiredFieldMissing,
352 )),
353 }
354 }
355
356 #[must_use]
358 pub(crate) fn mutation_managed_timestamp_regression() -> Self {
359 Self {
360 class: ErrorClass::InvariantViolation,
361 origin: ErrorOrigin::Executor,
362 detail: Some(ErrorDetail::Executor(
363 ExecutorErrorDetail::MutationManagedTimestampRegression,
364 )),
365 }
366 }
367
368 pub(crate) fn mutation_constraint_violation(diagnostic: ConstraintDiagnostic) -> Self {
370 Self {
371 class: ErrorClass::InvariantViolation,
372 origin: ErrorOrigin::Executor,
373 detail: Some(ErrorDetail::Executor(
374 ExecutorErrorDetail::ConstraintViolation {
375 diagnostic: Box::new(diagnostic),
376 },
377 )),
378 }
379 }
380
381 pub(crate) fn accepted_row_constraint_program_corrupt() -> Self {
383 Self {
384 class: ErrorClass::Corruption,
385 origin: ErrorOrigin::Executor,
386 detail: Some(ErrorDetail::Executor(
387 ExecutorErrorDetail::AcceptedRowConstraintProgramCorrupt,
388 )),
389 }
390 }
391
392 pub(crate) fn mutation_constraint_activation_write_blocked(
394 diagnostic: ConstraintDiagnostic,
395 ) -> Self {
396 Self {
397 class: ErrorClass::Conflict,
398 origin: ErrorOrigin::Executor,
399 detail: Some(ErrorDetail::Executor(
400 ExecutorErrorDetail::ConstraintActivationWriteBlocked {
401 diagnostic: Box::new(diagnostic),
402 },
403 )),
404 }
405 }
406
407 pub(crate) fn mutation_structural_field_unknown(_entity_path: &str, _field_name: &str) -> Self {
409 Self::executor_invariant()
410 }
411
412 pub(crate) fn scalar_page_cursor_boundary_order_required() -> Self {
414 Self::query_executor_invariant()
415 }
416
417 pub(crate) fn scalar_page_cursor_boundary_after_ordering_required() -> Self {
419 Self::query_executor_invariant()
420 }
421
422 pub(crate) fn scalar_page_pagination_after_ordering_required() -> Self {
424 Self::query_executor_invariant()
425 }
426
427 pub(crate) fn fast_stream_route_kind_request_match_required() -> Self {
429 Self::query_executor_invariant()
430 }
431
432 pub(crate) fn secondary_index_prefix_spec_required() -> Self {
434 Self::query_executor_invariant()
435 }
436
437 pub(crate) fn index_range_limit_spec_required() -> Self {
439 Self::query_executor_invariant()
440 }
441
442 pub(crate) fn mutation_atomic_save_duplicate_key(_entity_path: &str, _key: impl Sized) -> Self {
444 Self {
445 class: ErrorClass::Conflict,
446 origin: ErrorOrigin::Executor,
447 detail: Some(ErrorDetail::Executor(
448 ExecutorErrorDetail::MutationBatchDuplicateKey,
449 )),
450 }
451 }
452
453 pub(crate) fn mutation_batch_empty() -> Self {
455 Self::mutation_batch_unsupported(ExecutorErrorDetail::MutationBatchEmpty)
456 }
457
458 pub(crate) fn mutation_batch_too_many_items() -> Self {
460 Self::mutation_batch_unsupported(ExecutorErrorDetail::MutationBatchTooManyItems)
461 }
462
463 pub(crate) fn mutation_batch_staged_bytes_exceeded() -> Self {
465 Self::mutation_batch_unsupported(ExecutorErrorDetail::MutationBatchStagedBytesExceeded)
466 }
467
468 pub(crate) fn mutation_batch_result_bytes_exceeded() -> Self {
470 Self::mutation_batch_unsupported(ExecutorErrorDetail::MutationBatchResultBytesExceeded)
471 }
472
473 pub(crate) fn mutation_batch_entity_mismatch() -> Self {
475 Self {
476 class: ErrorClass::Conflict,
477 origin: ErrorOrigin::Executor,
478 detail: Some(ErrorDetail::Executor(
479 ExecutorErrorDetail::MutationBatchEntityMismatch,
480 )),
481 }
482 }
483
484 fn mutation_batch_unsupported(detail: ExecutorErrorDetail) -> Self {
485 Self {
486 class: ErrorClass::Unsupported,
487 origin: ErrorOrigin::Executor,
488 detail: Some(ErrorDetail::Executor(detail)),
489 }
490 }
491
492 pub(crate) fn mutation_index_store_generation_changed(
494 _expected_generation: u64,
495 _observed_generation: u64,
496 ) -> Self {
497 Self::executor_invariant()
498 }
499
500 #[cold]
502 #[inline(never)]
503 pub(crate) fn planner_invariant() -> Self {
504 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Planner)
505 }
506
507 pub(crate) fn query_invalid_logical_plan() -> Self {
509 Self::planner_invariant()
510 }
511
512 pub(crate) fn store_invariant() -> Self {
514 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Store)
515 }
516
517 #[cold]
519 #[inline(never)]
520 pub(crate) fn store_internal() -> Self {
521 Self::new(ErrorClass::Internal, ErrorOrigin::Store)
522 }
523
524 pub(crate) fn commit_memory_id_unconfigured() -> Self {
526 Self::store_internal()
527 }
528
529 pub(crate) fn commit_store_uninitialized() -> Self {
531 Self::store_invariant()
532 }
533
534 pub(crate) fn commit_memory_id_mismatch(_cached_id: u8, _configured_id: u8) -> Self {
536 Self::store_internal()
537 }
538
539 pub(crate) fn commit_memory_stable_key_mismatch(
541 _cached_key: &str,
542 _configured_key: &str,
543 ) -> Self {
544 Self::store_internal()
545 }
546
547 pub(crate) fn database_incarnation_generation_failed() -> Self {
549 Self::store_internal()
550 }
551
552 pub(crate) fn database_incarnation_invalid() -> Self {
554 Self::store_corruption()
555 }
556
557 pub(crate) fn recovery_unsupported_database_format(found: Option<u16>, required: u16) -> Self {
559 Self {
560 class: ErrorClass::IncompatiblePersistedFormat,
561 origin: ErrorOrigin::Recovery,
562 detail: Some(ErrorDetail::Recovery(
563 RecoveryErrorDetail::UnsupportedFormatVersion { found, required },
564 )),
565 }
566 }
567
568 pub(crate) fn recovery_malformed_database_format_marker(
570 reason: RecoveryFormatMarkerError,
571 ) -> Self {
572 Self {
573 class: ErrorClass::Corruption,
574 origin: ErrorOrigin::Recovery,
575 detail: Some(ErrorDetail::Recovery(
576 RecoveryErrorDetail::MalformedFormatMarker { reason },
577 )),
578 }
579 }
580
581 pub(crate) fn recovery_database_format_control_unavailable() -> Self {
583 Self::new(ErrorClass::Internal, ErrorOrigin::Recovery)
584 }
585
586 pub(crate) fn commit_control_memory_growth_failed() -> Self {
588 Self::store_internal()
589 }
590
591 #[cfg(not(test))]
593 pub(crate) fn database_format_memory_registration_failed(_err: impl Sized) -> Self {
594 Self::store_internal()
595 }
596
597 pub(crate) fn recovery_effect_verification_failed() -> Self {
599 Self::store_corruption()
600 }
601
602 #[cold]
604 #[inline(never)]
605 pub(crate) fn index_internal() -> Self {
606 Self::new(ErrorClass::Internal, ErrorOrigin::Index)
607 }
608
609 pub(crate) fn structural_index_removal_entity_key_required() -> Self {
611 Self::index_internal()
612 }
613
614 pub(crate) fn structural_index_insertion_entity_key_required() -> Self {
616 Self::index_internal()
617 }
618
619 pub(crate) fn index_commit_op_old_entity_key_required() -> Self {
621 Self::index_internal()
622 }
623
624 pub(crate) fn index_commit_op_new_entity_key_required() -> Self {
626 Self::index_internal()
627 }
628
629 #[cfg(test)]
631 pub(crate) fn query_internal() -> Self {
632 Self::new(ErrorClass::Internal, ErrorOrigin::Query)
633 }
634
635 #[cold]
637 #[inline(never)]
638 pub(crate) fn query_unsupported() -> Self {
639 Self::new(ErrorClass::Unsupported, ErrorOrigin::Query)
640 }
641
642 #[cold]
645 #[inline(never)]
646 pub(crate) fn query_stale_accepted_schema_revision(
647 _expected_revision: u64,
648 _current_revision: Option<u64>,
649 ) -> Self {
650 Self {
651 class: ErrorClass::Conflict,
652 origin: ErrorOrigin::Query,
653 detail: Some(ErrorDetail::Query(QueryErrorDetail::StaleSchemaRevision)),
654 }
655 }
656
657 #[cold]
659 #[inline(never)]
660 #[cfg(feature = "sql")]
661 pub(crate) fn query_schema_ddl_admission(error: SchemaDdlAdmissionError) -> Self {
662 Self {
663 class: ErrorClass::Unsupported,
664 origin: ErrorOrigin::Query,
665 detail: Some(ErrorDetail::Query(QueryErrorDetail::SchemaDdlAdmission {
666 error,
667 })),
668 }
669 }
670
671 #[cold]
673 #[inline(never)]
674 pub(crate) fn query_numeric_overflow() -> Self {
675 Self {
676 class: ErrorClass::Unsupported,
677 origin: ErrorOrigin::Query,
678 detail: Some(ErrorDetail::Query(QueryErrorDetail::NumericOverflow)),
679 }
680 }
681
682 #[cold]
685 #[inline(never)]
686 pub(crate) fn query_numeric_not_representable() -> Self {
687 Self {
688 class: ErrorClass::Unsupported,
689 origin: ErrorOrigin::Query,
690 detail: Some(ErrorDetail::Query(
691 QueryErrorDetail::NumericNotRepresentable,
692 )),
693 }
694 }
695
696 #[cold]
698 #[inline(never)]
699 pub(crate) fn serialize_internal() -> Self {
700 Self::new(ErrorClass::Internal, ErrorOrigin::Serialize)
701 }
702
703 pub(crate) fn persisted_row_encode_failed(_detail: impl Sized) -> Self {
705 Self::persisted_row_encode_internal()
706 }
707
708 pub(crate) fn persisted_row_encode_internal() -> Self {
710 Self::serialize_internal()
711 }
712
713 pub(crate) fn persisted_row_field_encode_internal(_field_name: &str) -> Self {
715 Self::persisted_row_encode_internal()
716 }
717
718 #[cold]
720 #[inline(never)]
721 pub(crate) fn store_corruption() -> Self {
722 Self::new(ErrorClass::Corruption, ErrorOrigin::Store)
723 }
724
725 pub(crate) fn commit_corruption() -> Self {
727 Self::store_corruption()
728 }
729
730 pub(crate) fn commit_component_corruption() -> Self {
732 Self::commit_corruption()
733 }
734
735 pub(crate) fn commit_id_generation_failed() -> Self {
737 Self::store_internal()
738 }
739
740 pub(crate) fn commit_marker_payload_exceeds_u32_length_limit() -> Self {
742 Self::store_unsupported()
743 }
744
745 pub(crate) fn commit_component_length_invalid() -> Self {
747 Self::commit_corruption()
748 }
749
750 pub(crate) fn commit_marker_exceeds_max_size() -> Self {
752 Self::commit_corruption()
753 }
754
755 pub(crate) fn commit_control_slot_exceeds_max_size() -> Self {
757 Self::store_unsupported()
758 }
759
760 pub(crate) fn commit_control_slot_marker_bytes_exceed_u32_length_limit() -> Self {
762 Self::store_unsupported()
763 }
764
765 pub(crate) fn startup_index_rebuild_invalid_data_key() -> Self {
767 Self::store_corruption()
768 }
769
770 #[cold]
772 #[inline(never)]
773 pub(crate) fn index_corruption() -> Self {
774 Self::new(ErrorClass::Corruption, ErrorOrigin::Index)
775 }
776
777 pub(crate) fn index_unique_validation_corruption() -> Self {
779 Self::index_plan_index_corruption()
780 }
781
782 pub(crate) fn structural_index_entry_corruption() -> Self {
784 Self::index_plan_index_corruption()
785 }
786
787 pub(crate) fn index_unique_validation_entity_key_required() -> Self {
789 Self::index_invariant()
790 }
791
792 pub(crate) fn index_unique_validation_row_deserialize_failed() -> Self {
794 Self::index_plan_serialize_corruption()
795 }
796
797 pub(crate) fn index_unique_validation_primary_key_decode_failed() -> Self {
799 Self::index_plan_serialize_corruption()
800 }
801
802 pub(crate) fn index_unique_validation_key_rebuild_failed() -> Self {
804 Self::index_plan_serialize_corruption()
805 }
806
807 pub(crate) fn index_unique_validation_row_required() -> Self {
809 Self::index_plan_store_corruption()
810 }
811
812 pub(crate) fn index_only_predicate_component_required() -> Self {
814 Self::index_invariant()
815 }
816
817 pub(crate) fn index_scan_continuation_anchor_within_envelope_required() -> Self {
819 Self::index_invariant()
820 }
821
822 pub(crate) fn index_scan_continuation_advancement_required() -> Self {
824 Self::index_invariant()
825 }
826
827 pub(crate) fn index_scan_key_corrupted_during(
829 _context: &'static str,
830 _err: impl Sized,
831 ) -> Self {
832 Self::index_corruption()
833 }
834
835 pub(crate) fn index_projection_component_required(
837 _index_name: &str,
838 _component_index: usize,
839 ) -> Self {
840 Self::index_invariant()
841 }
842
843 pub(crate) fn index_entry_decode_failed() -> Self {
845 Self::index_corruption()
846 }
847
848 pub(crate) fn serialize_corruption() -> Self {
850 Self::new(ErrorClass::Corruption, ErrorOrigin::Serialize)
851 }
852
853 pub(crate) fn persisted_row_decode_corruption() -> Self {
855 Self::serialize_corruption()
856 }
857
858 pub(crate) fn persisted_row_layout_outside_accepted_window() -> Self {
860 Self {
861 class: ErrorClass::Corruption,
862 origin: ErrorOrigin::Serialize,
863 detail: Some(ErrorDetail::Serialize(
864 SerializeErrorDetail::PersistedRowLayoutOutsideAcceptedWindow,
865 )),
866 }
867 }
868
869 pub(crate) fn persisted_row_slot_count_mismatch() -> Self {
871 Self {
872 class: ErrorClass::Corruption,
873 origin: ErrorOrigin::Serialize,
874 detail: Some(ErrorDetail::Serialize(
875 SerializeErrorDetail::PersistedRowSlotCountMismatch,
876 )),
877 }
878 }
879
880 pub(crate) fn persisted_row_field_decode_failed(field_name: &str, _detail: impl Sized) -> Self {
882 Self::persisted_row_field_decode_corruption(field_name)
883 }
884
885 pub(crate) fn persisted_row_field_decode_corruption(_field_name: &str) -> Self {
887 Self::persisted_row_decode_corruption()
888 }
889
890 pub(crate) fn persisted_row_field_kind_decode_failed(
892 field_name: &str,
893 _field_kind: impl fmt::Debug,
894 _detail: impl Sized,
895 ) -> Self {
896 Self::persisted_row_field_decode_corruption(field_name)
897 }
898
899 pub(crate) fn persisted_row_field_payload_exact_len_required(field_name: &str) -> Self {
901 Self::persisted_row_field_decode_corruption(field_name)
902 }
903
904 pub(crate) fn persisted_row_field_payload_must_be_empty(field_name: &str) -> Self {
906 Self::persisted_row_field_decode_corruption(field_name)
907 }
908
909 pub(crate) fn persisted_row_field_payload_invalid_byte(field_name: &str) -> Self {
911 Self::persisted_row_field_decode_corruption(field_name)
912 }
913
914 pub(crate) fn persisted_row_field_payload_non_finite(field_name: &str) -> Self {
916 Self::persisted_row_field_decode_corruption(field_name)
917 }
918
919 pub(crate) fn persisted_row_field_text_payload_invalid_utf8(field_name: &str) -> Self {
921 Self::persisted_row_field_decode_corruption(field_name)
922 }
923
924 pub(crate) fn persisted_row_slot_lookup_out_of_bounds(_model_path: &str, _slot: usize) -> Self {
926 Self::index_invariant()
927 }
928
929 pub(crate) fn persisted_row_slot_cache_lookup_out_of_bounds(
931 _model_path: &str,
932 _slot: usize,
933 ) -> Self {
934 Self::index_invariant()
935 }
936
937 pub(crate) fn persisted_row_primary_key_not_primary_key_encodable(
939 _data_key: impl fmt::Debug,
940 _detail: impl Sized,
941 ) -> Self {
942 Self::persisted_row_decode_corruption()
943 }
944
945 pub(crate) fn persisted_row_primary_key_slot_missing(_data_key: impl fmt::Debug) -> Self {
947 Self::persisted_row_decode_corruption()
948 }
949
950 pub(crate) fn persisted_row_key_mismatch() -> Self {
952 Self::store_corruption()
953 }
954
955 pub(crate) fn persisted_row_declared_field_missing(field_name: &str) -> Self {
957 Self::persisted_row_field_decode_corruption(field_name)
958 }
959
960 pub(crate) fn reverse_index_ordinal_overflow(
962 _source_path: &str,
963 _field_name: &str,
964 _target_path: &str,
965 _detail: impl Sized,
966 ) -> Self {
967 Self::index_internal()
968 }
969
970 pub(crate) fn reverse_index_entry_corrupted(
972 _source_path: &str,
973 _field_name: &str,
974 _target_path: &str,
975 _index_key: impl fmt::Debug,
976 _detail: impl Sized,
977 ) -> Self {
978 Self::index_corruption()
979 }
980
981 pub(crate) fn relation_target_store_missing(
983 _source_path: &str,
984 _field_name: &str,
985 _target_path: &str,
986 _store_path: &str,
987 _detail: impl Sized,
988 ) -> Self {
989 Self::executor_internal()
990 }
991
992 pub(crate) fn relation_target_key_decode_failed(
994 _context_label: &str,
995 _source_path: &str,
996 _field_name: &str,
997 _target_path: &str,
998 _detail: impl Sized,
999 ) -> Self {
1000 Self::identity_corruption()
1001 }
1002
1003 pub(crate) fn relation_target_entity_mismatch(
1005 _context_label: &str,
1006 _source_path: &str,
1007 _field_name: &str,
1008 _target_path: &str,
1009 _target_entity_name: &str,
1010 _expected_tag: impl Sized,
1011 _actual_tag: impl Sized,
1012 ) -> Self {
1013 Self::store_corruption()
1014 }
1015
1016 pub(crate) fn relation_source_row_decode_failed(
1018 _source_path: &str,
1019 _field_name: &str,
1020 _target_path: &str,
1021 _detail: impl Sized,
1022 ) -> Self {
1023 Self::persisted_row_decode_corruption()
1024 }
1025
1026 pub(crate) fn relation_source_row_unsupported_scalar_relation_key(
1028 _source_path: &str,
1029 _field_name: &str,
1030 _target_path: &str,
1031 ) -> Self {
1032 Self::persisted_row_decode_corruption()
1033 }
1034
1035 pub(crate) fn relation_source_row_unsupported_key_kind(_field_kind: impl fmt::Debug) -> Self {
1037 Self::persisted_row_decode_corruption()
1038 }
1039
1040 pub(crate) fn bytes_covering_component_payload_empty() -> Self {
1042 Self::index_corruption()
1043 }
1044
1045 pub(crate) fn bytes_covering_bool_payload_truncated() -> Self {
1047 Self::index_corruption()
1048 }
1049
1050 pub(crate) fn bytes_covering_component_payload_invalid_length() -> Self {
1052 Self::index_corruption()
1053 }
1054
1055 pub(crate) fn bytes_covering_bool_payload_invalid_value() -> Self {
1057 Self::index_corruption()
1058 }
1059
1060 pub(crate) fn bytes_covering_text_payload_invalid_terminator() -> Self {
1062 Self::index_corruption()
1063 }
1064
1065 pub(crate) fn bytes_covering_text_payload_trailing_bytes() -> Self {
1067 Self::index_corruption()
1068 }
1069
1070 pub(crate) fn bytes_covering_text_payload_invalid_utf8() -> Self {
1072 Self::index_corruption()
1073 }
1074
1075 pub(crate) fn bytes_covering_text_payload_invalid_escape_byte() -> Self {
1077 Self::index_corruption()
1078 }
1079
1080 pub(crate) fn bytes_covering_text_payload_missing_terminator() -> Self {
1082 Self::index_corruption()
1083 }
1084
1085 pub(crate) fn identity_corruption() -> Self {
1087 Self::new(ErrorClass::Corruption, ErrorOrigin::Identity)
1088 }
1089
1090 pub(crate) fn identity_state_corruption() -> Self {
1092 Self::identity_corruption()
1093 }
1094
1095 pub(crate) fn identity_state_conflict() -> Self {
1097 Self::new(ErrorClass::Conflict, ErrorOrigin::Identity)
1098 }
1099
1100 pub(crate) fn identity_state_capacity_exhausted() -> Self {
1102 Self::new(ErrorClass::Unsupported, ErrorOrigin::Identity)
1103 }
1104
1105 pub(crate) fn identity_exhausted() -> Self {
1107 Self::new(ErrorClass::Unsupported, ErrorOrigin::Identity)
1108 }
1109
1110 pub(crate) fn identity_candidate_count_exhausted() -> Self {
1112 Self::new(ErrorClass::Unsupported, ErrorOrigin::Identity)
1113 }
1114
1115 #[cold]
1117 #[inline(never)]
1118 pub(crate) fn store_unsupported() -> Self {
1119 Self::new(ErrorClass::Unsupported, ErrorOrigin::Store)
1120 }
1121
1122 pub(crate) fn schema_application_conflict() -> Self {
1124 Self::new(ErrorClass::Conflict, ErrorOrigin::Store)
1125 }
1126
1127 pub(crate) fn schema_migration(reason: diagnostic_code::SchemaMigrationCode) -> Self {
1129 let class = match reason.diagnostic_code() {
1130 diagnostic_code::DiagnosticCode::RuntimeConflict => ErrorClass::Conflict,
1131 diagnostic_code::DiagnosticCode::RuntimeCorruption => ErrorClass::Corruption,
1132 diagnostic_code::DiagnosticCode::RuntimeUnsupported => ErrorClass::Unsupported,
1133 _ => ErrorClass::Internal,
1134 };
1135 Self {
1136 class,
1137 origin: ErrorOrigin::Store,
1138 detail: Some(ErrorDetail::Store(StoreError::SchemaMigration { reason })),
1139 }
1140 }
1141
1142 pub(crate) fn schema_ddl_publication_race_lost(_entity_path: &str) -> Self {
1144 Self {
1145 class: ErrorClass::Unsupported,
1146 origin: ErrorOrigin::Store,
1147 detail: Some(ErrorDetail::Store(StoreError::SchemaDdlPublicationRaceLost)),
1148 }
1149 }
1150
1151 #[cfg(feature = "sql")]
1153 pub(crate) fn schema_ddl_rewrite_requires_migration(_entity_path: &str) -> Self {
1154 Self {
1155 class: ErrorClass::Unsupported,
1156 origin: ErrorOrigin::Store,
1157 detail: Some(ErrorDetail::Store(
1158 StoreError::SchemaDdlRewriteRequiresMigration,
1159 )),
1160 }
1161 }
1162
1163 pub(crate) fn journal_mutation_revision_exhausted() -> Self {
1165 Self {
1166 class: ErrorClass::Unsupported,
1167 origin: ErrorOrigin::Store,
1168 detail: Some(ErrorDetail::Store(
1169 StoreError::JournalMutationRevisionExhausted,
1170 )),
1171 }
1172 }
1173
1174 pub(crate) fn schema_transition_budget_exceeded(
1176 resource: SchemaTransitionBudgetResource,
1177 ) -> Self {
1178 Self {
1179 class: ErrorClass::Unsupported,
1180 origin: ErrorOrigin::Store,
1181 detail: Some(ErrorDetail::Store(
1182 StoreError::SchemaTransitionBudgetExceeded { resource },
1183 )),
1184 }
1185 }
1186
1187 pub(crate) fn unsupported_entity_tag_in_data_store(
1189 _entity_tag: crate::types::EntityTag,
1190 ) -> Self {
1191 Self::store_unsupported()
1192 }
1193
1194 #[cfg(not(test))]
1196 pub(crate) fn commit_memory_id_registration_failed(_err: impl Sized) -> Self {
1197 Self::store_internal()
1198 }
1199
1200 pub(crate) fn index_unsupported() -> Self {
1202 Self::new(ErrorClass::Unsupported, ErrorOrigin::Index)
1203 }
1204
1205 pub(crate) fn index_component_exceeds_max_size() -> Self {
1207 Self::index_unsupported()
1208 }
1209
1210 pub(crate) fn serialize_unsupported() -> Self {
1212 Self::new(ErrorClass::Unsupported, ErrorOrigin::Serialize)
1213 }
1214
1215 pub(crate) fn cursor_invalid_continuation() -> Self {
1217 Self::new(ErrorClass::Unsupported, ErrorOrigin::Cursor)
1218 }
1219
1220 pub(crate) fn serialize_incompatible_persisted_format() -> Self {
1222 Self::new(
1223 ErrorClass::IncompatiblePersistedFormat,
1224 ErrorOrigin::Serialize,
1225 )
1226 }
1227
1228 #[cfg(feature = "sql")]
1231 pub(crate) fn query_unsupported_sql_feature(feature: diagnostic_code::SqlFeatureCode) -> Self {
1232 Self {
1233 class: ErrorClass::Unsupported,
1234 origin: ErrorOrigin::Query,
1235 detail: Some(ErrorDetail::Query(
1236 QueryErrorDetail::UnsupportedSqlFeature { feature },
1237 )),
1238 }
1239 }
1240
1241 #[cfg(feature = "sql")]
1244 pub(crate) fn query_sql_lowering(reason: diagnostic_code::SqlLoweringCode) -> Self {
1245 Self {
1246 class: ErrorClass::Unsupported,
1247 origin: ErrorOrigin::Query,
1248 detail: Some(ErrorDetail::Query(QueryErrorDetail::SqlLowering { reason })),
1249 }
1250 }
1251
1252 pub(crate) fn query_unsupported_projection(
1255 reason: diagnostic_code::QueryProjectionCode,
1256 ) -> Self {
1257 Self {
1258 class: ErrorClass::Unsupported,
1259 origin: ErrorOrigin::Query,
1260 detail: Some(ErrorDetail::Query(
1261 QueryErrorDetail::UnsupportedProjection { reason },
1262 )),
1263 }
1264 }
1265
1266 pub(crate) fn query_unknown_aggregate_target_field() -> Self {
1268 Self {
1269 class: ErrorClass::Unsupported,
1270 origin: ErrorOrigin::Query,
1271 detail: Some(ErrorDetail::Query(
1272 QueryErrorDetail::UnknownAggregateTargetField,
1273 )),
1274 }
1275 }
1276
1277 #[cfg(feature = "sql")]
1280 pub(crate) fn query_sql_surface_mismatch(
1281 mismatch: diagnostic_code::SqlSurfaceMismatchCode,
1282 ) -> Self {
1283 Self {
1284 class: ErrorClass::Unsupported,
1285 origin: ErrorOrigin::Query,
1286 detail: Some(ErrorDetail::Query(QueryErrorDetail::SqlSurfaceMismatch {
1287 mismatch,
1288 })),
1289 }
1290 }
1291
1292 pub(crate) fn query_sql_write_boundary(
1294 boundary: diagnostic_code::SqlWriteBoundaryCode,
1295 ) -> Self {
1296 Self {
1297 class: ErrorClass::Unsupported,
1298 origin: ErrorOrigin::Query,
1299 detail: Some(ErrorDetail::Query(QueryErrorDetail::SqlWriteBoundary {
1300 boundary,
1301 })),
1302 }
1303 }
1304
1305 pub fn store_not_found(_key: impl Sized) -> Self {
1306 Self {
1307 class: ErrorClass::NotFound,
1308 origin: ErrorOrigin::Store,
1309 detail: Some(ErrorDetail::Store(StoreError::NotFound)),
1310 }
1311 }
1312
1313 pub fn unsupported_entity_path(_path: impl Sized) -> Self {
1315 Self::store_unsupported()
1316 }
1317
1318 #[cold]
1320 #[inline(never)]
1321 pub(crate) fn index_plan_corruption(origin: ErrorOrigin) -> Self {
1322 Self::new(ErrorClass::Corruption, origin)
1323 }
1324
1325 #[cold]
1327 #[inline(never)]
1328 pub(crate) fn index_plan_index_corruption() -> Self {
1329 Self::index_plan_corruption(ErrorOrigin::Index)
1330 }
1331
1332 #[cold]
1334 #[inline(never)]
1335 pub(crate) fn index_plan_store_corruption() -> Self {
1336 Self::index_plan_corruption(ErrorOrigin::Store)
1337 }
1338
1339 #[cold]
1341 #[inline(never)]
1342 pub(crate) fn index_plan_serialize_corruption() -> Self {
1343 Self::index_plan_corruption(ErrorOrigin::Serialize)
1344 }
1345
1346 #[cfg(test)]
1348 pub(crate) fn index_plan_invariant(origin: ErrorOrigin) -> Self {
1349 Self::new(ErrorClass::InvariantViolation, origin)
1350 }
1351
1352 #[cfg(test)]
1354 pub(crate) fn index_plan_store_invariant() -> Self {
1355 Self::index_plan_invariant(ErrorOrigin::Store)
1356 }
1357
1358 pub(crate) fn index_conflict() -> Self {
1364 Self::new(ErrorClass::Conflict, ErrorOrigin::Index)
1365 }
1366}
1367
1368impl From<diagnostic_code::QueryReadAdmissionCode> for InternalError {
1369 fn from(reason: diagnostic_code::QueryReadAdmissionCode) -> Self {
1370 Self {
1371 class: ErrorClass::Unsupported,
1372 origin: ErrorOrigin::Query,
1373 detail: Some(ErrorDetail::Query(QueryErrorDetail::QueryReadAdmission {
1374 reason,
1375 })),
1376 }
1377 }
1378}
1379
1380impl fmt::Debug for InternalError {
1381 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1382 fmt_compact_diagnostic(
1383 f,
1384 self.diagnostic_code(),
1385 self.detail
1386 .as_ref()
1387 .and_then(ErrorDetail::diagnostic_detail),
1388 )
1389 }
1390}
1391
1392impl fmt::Display for InternalError {
1393 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1394 f.write_str(self.message())
1395 }
1396}
1397
1398impl std::error::Error for InternalError {}
1399
1400#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq)]
1408pub enum ConstraintDiagnosticKind {
1409 Check,
1411
1412 NotNull,
1414
1415 Relation,
1417
1418 TargetedRule,
1420
1421 Unique,
1423}
1424
1425impl ConstraintDiagnosticKind {
1426 #[must_use]
1428 pub const fn as_str(self) -> &'static str {
1429 match self {
1430 Self::Check => "check",
1431 Self::NotNull => "not_null",
1432 Self::Relation => "relation",
1433 Self::TargetedRule => "targeted_rule",
1434 Self::Unique => "unique",
1435 }
1436 }
1437}
1438
1439#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq)]
1448pub enum ConstraintValuePathComponent {
1449 RootField { field_id: u32 },
1451
1452 RecordMember {
1454 composite_type_id: u32,
1455 member_id: u32,
1456 },
1457
1458 TupleElement {
1460 composite_type_id: u32,
1461 ordinal: u32,
1462 },
1463
1464 Newtype { composite_type_id: u32 },
1466
1467 EnumVariant { enum_type_id: u32, variant_id: u32 },
1469
1470 ListElement { index: u32 },
1472
1473 SetElement { index: u32 },
1475
1476 MapEntryKey { index: u32 },
1478
1479 MapEntryValue { index: u32 },
1481}
1482
1483impl fmt::Display for ConstraintValuePathComponent {
1484 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1485 match self {
1486 Self::RootField { field_id } => write!(f, "field#{field_id}"),
1487 Self::RecordMember {
1488 composite_type_id,
1489 member_id,
1490 } => write!(f, "record#{composite_type_id}.member#{member_id}"),
1491 Self::TupleElement {
1492 composite_type_id,
1493 ordinal,
1494 } => write!(f, "tuple#{composite_type_id}[{ordinal}]"),
1495 Self::Newtype { composite_type_id } => write!(f, "newtype#{composite_type_id}"),
1496 Self::EnumVariant {
1497 enum_type_id,
1498 variant_id,
1499 } => write!(f, "enum#{enum_type_id}.variant#{variant_id}"),
1500 Self::ListElement { index } => write!(f, "list[{index}]"),
1501 Self::SetElement { index } => write!(f, "set[{index}]"),
1502 Self::MapEntryKey { index } => write!(f, "map[{index}].key"),
1503 Self::MapEntryValue { index } => write!(f, "map[{index}].value"),
1504 }
1505 }
1506}
1507
1508#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
1515pub struct ConstraintValuePath {
1516 components: Vec<ConstraintValuePathComponent>,
1517}
1518
1519impl ConstraintValuePath {
1520 #[must_use]
1522 pub(crate) const fn new(components: Vec<ConstraintValuePathComponent>) -> Self {
1523 Self { components }
1524 }
1525
1526 #[must_use]
1528 pub const fn components(&self) -> &[ConstraintValuePathComponent] {
1529 self.components.as_slice()
1530 }
1531}
1532
1533impl fmt::Display for ConstraintValuePath {
1534 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1535 for (ordinal, component) in self.components.iter().enumerate() {
1536 if ordinal != 0 {
1537 f.write_str("/")?;
1538 }
1539 component.fmt(f)?;
1540 }
1541 Ok(())
1542 }
1543}
1544
1545#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq)]
1553pub enum ConstraintDiagnosticContext {
1554 Integrity,
1556
1557 MigrationValidation,
1559
1560 WriteAdmission,
1562}
1563
1564impl ConstraintDiagnosticContext {
1565 #[must_use]
1567 pub const fn as_str(self) -> &'static str {
1568 match self {
1569 Self::Integrity => "integrity",
1570 Self::MigrationValidation => "migration_validation",
1571 Self::WriteAdmission => "write_admission",
1572 }
1573 }
1574}
1575
1576#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
1585pub struct ConstraintDiagnostic {
1586 constraint_id: u32,
1587 constraint_name: String,
1588 constraint_kind: ConstraintDiagnosticKind,
1589 entity: String,
1590 primary_key: Option<Vec<u8>>,
1591 field_paths: Vec<String>,
1592 value_path: Option<Box<ConstraintValuePath>>,
1593 context: ConstraintDiagnosticContext,
1594 error_code: u16,
1595}
1596
1597impl ConstraintDiagnostic {
1598 #[must_use]
1600 pub(crate) const fn write_violation(
1601 constraint_id: u32,
1602 constraint_name: String,
1603 constraint_kind: ConstraintDiagnosticKind,
1604 entity: String,
1605 primary_key: Option<Vec<u8>>,
1606 field_paths: Vec<String>,
1607 ) -> Self {
1608 Self {
1609 constraint_id,
1610 constraint_name,
1611 constraint_kind,
1612 entity,
1613 primary_key,
1614 field_paths,
1615 value_path: None,
1616 context: ConstraintDiagnosticContext::WriteAdmission,
1617 error_code: diagnostic_code::ErrorCode::RUNTIME_BOUNDARY_CONSTRAINT_VIOLATION.raw(),
1618 }
1619 }
1620
1621 #[must_use]
1623 pub(crate) fn write_targeted_rule_violation(
1624 constraint_id: u32,
1625 constraint_name: String,
1626 entity: String,
1627 primary_key: Option<Vec<u8>>,
1628 field_paths: Vec<String>,
1629 value_path: ConstraintValuePath,
1630 ) -> Self {
1631 Self {
1632 constraint_id,
1633 constraint_name,
1634 constraint_kind: ConstraintDiagnosticKind::TargetedRule,
1635 entity,
1636 primary_key,
1637 field_paths,
1638 value_path: Some(Box::new(value_path)),
1639 context: ConstraintDiagnosticContext::WriteAdmission,
1640 error_code: diagnostic_code::ErrorCode::RUNTIME_BOUNDARY_CONSTRAINT_VIOLATION.raw(),
1641 }
1642 }
1643
1644 #[must_use]
1646 pub(crate) const fn write_activation_blocked(
1647 constraint_id: u32,
1648 constraint_name: String,
1649 constraint_kind: ConstraintDiagnosticKind,
1650 entity: String,
1651 primary_key: Option<Vec<u8>>,
1652 field_paths: Vec<String>,
1653 ) -> Self {
1654 Self {
1655 constraint_id,
1656 constraint_name,
1657 constraint_kind,
1658 entity,
1659 primary_key,
1660 field_paths,
1661 value_path: None,
1662 context: ConstraintDiagnosticContext::WriteAdmission,
1663 error_code:
1664 diagnostic_code::ErrorCode::RUNTIME_BOUNDARY_CONSTRAINT_ACTIVATION_WRITE_BLOCKED
1665 .raw(),
1666 }
1667 }
1668
1669 #[must_use]
1671 pub(crate) const fn migration_validation(
1672 constraint_id: u32,
1673 constraint_name: String,
1674 constraint_kind: ConstraintDiagnosticKind,
1675 entity: String,
1676 primary_key: Vec<u8>,
1677 field_paths: Vec<String>,
1678 error_code: u16,
1679 ) -> Self {
1680 Self {
1681 constraint_id,
1682 constraint_name,
1683 constraint_kind,
1684 entity,
1685 primary_key: Some(primary_key),
1686 field_paths,
1687 value_path: None,
1688 context: ConstraintDiagnosticContext::MigrationValidation,
1689 error_code,
1690 }
1691 }
1692
1693 #[must_use]
1695 pub(crate) fn migration_targeted_rule_validation(
1696 constraint_id: u32,
1697 constraint_name: String,
1698 entity: String,
1699 primary_key: Vec<u8>,
1700 field_paths: Vec<String>,
1701 value_path: ConstraintValuePath,
1702 error_code: u16,
1703 ) -> Self {
1704 Self {
1705 constraint_id,
1706 constraint_name,
1707 constraint_kind: ConstraintDiagnosticKind::TargetedRule,
1708 entity,
1709 primary_key: Some(primary_key),
1710 field_paths,
1711 value_path: Some(Box::new(value_path)),
1712 context: ConstraintDiagnosticContext::MigrationValidation,
1713 error_code,
1714 }
1715 }
1716
1717 #[must_use]
1719 pub const fn constraint_id(&self) -> u32 {
1720 self.constraint_id
1721 }
1722
1723 #[must_use]
1725 pub const fn constraint_name(&self) -> &str {
1726 self.constraint_name.as_str()
1727 }
1728
1729 #[must_use]
1731 pub const fn constraint_kind(&self) -> ConstraintDiagnosticKind {
1732 self.constraint_kind
1733 }
1734
1735 #[must_use]
1737 pub const fn entity(&self) -> &str {
1738 self.entity.as_str()
1739 }
1740
1741 #[must_use]
1743 pub fn primary_key(&self) -> Option<&[u8]> {
1744 self.primary_key.as_deref()
1745 }
1746
1747 #[must_use]
1749 pub const fn field_paths(&self) -> &[String] {
1750 self.field_paths.as_slice()
1751 }
1752
1753 #[must_use]
1755 pub fn value_path(&self) -> Option<&ConstraintValuePath> {
1756 self.value_path.as_deref()
1757 }
1758
1759 #[must_use]
1761 pub const fn context(&self) -> ConstraintDiagnosticContext {
1762 self.context
1763 }
1764
1765 #[must_use]
1767 pub const fn error_code(&self) -> diagnostic_code::ErrorCode {
1768 diagnostic_code::ErrorCode::from_raw(self.error_code)
1769 }
1770
1771 #[must_use]
1773 pub const fn error_class(&self) -> diagnostic_code::ErrorClass {
1774 self.error_code().class()
1775 }
1776}
1777
1778pub enum ErrorDetail {
1786 Executor(ExecutorErrorDetail),
1788 Store(StoreError),
1789 Query(QueryErrorDetail),
1790 Recovery(RecoveryErrorDetail),
1791 Serialize(SerializeErrorDetail),
1793 }
1796
1797pub enum ExecutorErrorDetail {
1799 MutationRequiredFieldMissing,
1801 MutationManagedTimestampRegression,
1803 MutationDatabaseOwnedFieldExplicit,
1805 MutationBatchEmpty,
1807 MutationBatchTooManyItems,
1809 MutationBatchStagedBytesExceeded,
1811 MutationBatchResultBytesExceeded,
1813 MutationBatchEntityMismatch,
1815 MutationBatchDuplicateKey,
1817 ConstraintViolation {
1819 diagnostic: Box<ConstraintDiagnostic>,
1820 },
1821 AcceptedRowConstraintProgramCorrupt,
1823 ConstraintActivationWriteBlocked {
1825 diagnostic: Box<ConstraintDiagnostic>,
1826 },
1827}
1828
1829impl ExecutorErrorDetail {
1830 #[must_use]
1832 pub fn constraint_diagnostic(&self) -> Option<&ConstraintDiagnostic> {
1833 match self {
1834 Self::ConstraintActivationWriteBlocked { diagnostic }
1835 | Self::ConstraintViolation { diagnostic } => Some(diagnostic.as_ref()),
1836 Self::MutationRequiredFieldMissing
1837 | Self::MutationManagedTimestampRegression
1838 | Self::MutationDatabaseOwnedFieldExplicit
1839 | Self::MutationBatchEmpty
1840 | Self::MutationBatchTooManyItems
1841 | Self::MutationBatchStagedBytesExceeded
1842 | Self::MutationBatchResultBytesExceeded
1843 | Self::MutationBatchEntityMismatch
1844 | Self::MutationBatchDuplicateKey
1845 | Self::AcceptedRowConstraintProgramCorrupt => None,
1846 }
1847 }
1848}
1849
1850pub enum SerializeErrorDetail {
1852 PersistedRowLayoutOutsideAcceptedWindow,
1854
1855 PersistedRowSlotCountMismatch,
1857}
1858
1859pub enum RecoveryErrorDetail {
1866 UnsupportedFormatVersion { found: Option<u16>, required: u16 },
1867
1868 MalformedFormatMarker { reason: RecoveryFormatMarkerError },
1869}
1870
1871#[derive(Clone, Copy, Eq, PartialEq)]
1873pub enum RecoveryFormatMarkerError {
1874 Magic,
1875 Checksum,
1876 State,
1877}
1878
1879pub enum StoreError {
1887 NotFound,
1888
1889 Corrupt,
1890
1891 InvariantViolation,
1892
1893 SchemaDdlPublicationRaceLost,
1894
1895 SchemaDdlRewriteRequiresMigration,
1896
1897 SchemaMigration {
1898 reason: diagnostic_code::SchemaMigrationCode,
1899 },
1900
1901 SchemaRowLayoutVersionExhausted,
1902
1903 JournalMutationRevisionExhausted,
1904
1905 SchemaTransitionBudgetExceeded {
1906 resource: SchemaTransitionBudgetResource,
1907 },
1908
1909 SchemaGeneratedFieldAfterDdlField,
1911
1912 SchemaGeneratedConstraintActivationStale,
1914}
1915
1916pub enum QueryErrorDetail {
1923 NumericOverflow,
1924
1925 NumericNotRepresentable,
1926
1927 UnsupportedSqlFeature {
1928 feature: diagnostic_code::SqlFeatureCode,
1929 },
1930
1931 SqlLowering {
1932 reason: diagnostic_code::SqlLoweringCode,
1933 },
1934
1935 UnsupportedProjection {
1936 reason: diagnostic_code::QueryProjectionCode,
1937 },
1938
1939 UnknownAggregateTargetField,
1940
1941 ResultShapeMismatch {
1942 reason: diagnostic_code::QueryResultShapeCode,
1943 },
1944
1945 QueryReadAdmission {
1946 reason: diagnostic_code::QueryReadAdmissionCode,
1947 },
1948
1949 SqlSurfaceMismatch {
1950 mismatch: diagnostic_code::SqlSurfaceMismatchCode,
1951 },
1952
1953 SqlWriteBoundary {
1954 boundary: diagnostic_code::SqlWriteBoundaryCode,
1955 },
1956
1957 SchemaDdlAdmission {
1958 error: SchemaDdlAdmissionError,
1959 },
1960
1961 StaleSchemaRevision,
1962}
1963
1964impl fmt::Display for QueryErrorDetail {
1965 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1966 f.write_str(COMPACT_QUERY_DIAGNOSTIC_MESSAGE)
1967 }
1968}
1969
1970impl std::error::Error for QueryErrorDetail {}
1971
1972#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1980pub enum SchemaTransitionBudgetResource {
1981 DeletionKeys,
1983 ProjectionEntries,
1985 ProjectionWorkUnits,
1987 SourceRows,
1989 SourceRowBytes,
1991 StagedRawBytes,
1993}
1994
1995#[derive(Clone, Copy, Eq, PartialEq)]
2004pub enum SchemaDdlAdmissionError {
2005 MissingExpectedSchemaVersion,
2006
2007 MissingNextSchemaVersion,
2008
2009 StaleExpectedSchemaVersion,
2010
2011 InvalidExpectedSchemaVersion,
2012
2013 InvalidNextSchemaVersion,
2014
2015 AcceptedSchemaChangeWithoutVersionBump,
2016
2017 EmptyVersionBump,
2018
2019 VersionGap,
2020
2021 VersionRollback,
2022
2023 FingerprintMethodMismatch,
2024
2025 UnsupportedTransitionClass,
2026
2027 PhysicalRunnerMissing,
2028
2029 ValidationFailed,
2030
2031 PublicationRaceLost,
2032
2033 InvalidAddColumnDefault,
2034
2035 InvalidAlterColumnDefault,
2036
2037 RowLayoutVersionExhausted,
2038
2039 GeneratedIndexDropRejected,
2040
2041 SchemaRewriteRequiresMigration,
2042
2043 SchemaTransitionBudgetExceeded {
2044 resource: SchemaTransitionBudgetResource,
2045 },
2046
2047 GeneratedFieldDefaultChangeRejected,
2048
2049 GeneratedFieldNullabilityChangeRejected,
2050}
2051
2052impl fmt::Display for SchemaDdlAdmissionError {
2053 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2054 f.write_str(COMPACT_QUERY_DIAGNOSTIC_MESSAGE)
2055 }
2056}
2057
2058impl std::error::Error for SchemaDdlAdmissionError {}
2059
2060impl fmt::Debug for ErrorDetail {
2061 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2062 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2063 }
2064}
2065
2066impl fmt::Debug for ExecutorErrorDetail {
2067 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2068 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2069 }
2070}
2071
2072impl fmt::Debug for StoreError {
2073 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2074 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2075 }
2076}
2077
2078impl fmt::Debug for QueryErrorDetail {
2079 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2080 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2081 }
2082}
2083
2084impl fmt::Debug for RecoveryErrorDetail {
2085 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2086 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2087 }
2088}
2089
2090impl fmt::Debug for SerializeErrorDetail {
2091 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2092 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2093 }
2094}
2095
2096impl fmt::Debug for RecoveryFormatMarkerError {
2097 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2098 fmt_compact_diagnostic(
2099 f,
2100 diagnostic_code::DiagnosticCode::RuntimeCorruption,
2101 Some(diagnostic_code::DiagnosticDetail::RuntimeKind {
2102 kind: diagnostic_code::RuntimeErrorKind::Corruption,
2103 }),
2104 )
2105 }
2106}
2107
2108impl fmt::Debug for SchemaDdlAdmissionError {
2109 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2110 fmt_compact_diagnostic(
2111 f,
2112 diagnostic_code::DiagnosticCode::SchemaDdlAdmission,
2113 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2114 reason: self.diagnostic_code(),
2115 }),
2116 )
2117 }
2118}
2119
2120fn fmt_compact_diagnostic(
2121 f: &mut fmt::Formatter<'_>,
2122 code: diagnostic_code::DiagnosticCode,
2123 detail: Option<diagnostic_code::DiagnosticDetail>,
2124) -> fmt::Result {
2125 write!(
2126 f,
2127 "{}",
2128 diagnostic_code::ErrorCode::from_parts(code, detail).raw()
2129 )
2130}
2131
2132impl ErrorDetail {
2133 #[must_use]
2135 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2136 match self {
2137 Self::Executor(error) => error.diagnostic_code(),
2138 Self::Store(error) => error.diagnostic_code(),
2139 Self::Query(error) => error.diagnostic_code(),
2140 Self::Recovery(error) => error.diagnostic_code(),
2141 Self::Serialize(error) => error.diagnostic_code(),
2142 }
2143 }
2144
2145 #[must_use]
2147 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2148 match self {
2149 Self::Executor(error) => error.diagnostic_detail(),
2150 Self::Store(error) => error.diagnostic_detail(),
2151 Self::Query(error) => error.diagnostic_detail(),
2152 Self::Recovery(error) => error.diagnostic_detail(),
2153 Self::Serialize(error) => error.diagnostic_detail(),
2154 }
2155 }
2156}
2157
2158impl ExecutorErrorDetail {
2159 #[must_use]
2161 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2162 match self {
2163 Self::MutationRequiredFieldMissing
2164 | Self::MutationDatabaseOwnedFieldExplicit
2165 | Self::MutationBatchEmpty
2166 | Self::MutationBatchTooManyItems
2167 | Self::MutationBatchStagedBytesExceeded
2168 | Self::MutationBatchResultBytesExceeded => {
2169 diagnostic_code::DiagnosticCode::RuntimeUnsupported
2170 }
2171 Self::MutationBatchEntityMismatch | Self::MutationBatchDuplicateKey => {
2172 diagnostic_code::DiagnosticCode::RuntimeConflict
2173 }
2174 Self::MutationManagedTimestampRegression => {
2175 diagnostic_code::DiagnosticCode::RuntimeInvariantViolation
2176 }
2177 Self::ConstraintViolation { diagnostic }
2178 | Self::ConstraintActivationWriteBlocked { diagnostic } => {
2179 diagnostic.error_code().diagnostic_code()
2180 }
2181 Self::AcceptedRowConstraintProgramCorrupt => {
2182 diagnostic_code::DiagnosticCode::RuntimeCorruption
2183 }
2184 }
2185 }
2186
2187 #[must_use]
2189 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2190 match self {
2191 Self::MutationRequiredFieldMissing => {
2192 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2193 boundary: diagnostic_code::RuntimeBoundaryCode::MutationRequiredFieldMissing,
2194 })
2195 }
2196 Self::MutationDatabaseOwnedFieldExplicit => {
2197 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2198 boundary:
2199 diagnostic_code::RuntimeBoundaryCode::MutationDatabaseOwnedFieldExplicit,
2200 })
2201 }
2202 Self::MutationBatchEmpty => Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2203 boundary: diagnostic_code::RuntimeBoundaryCode::MutationBatchEmpty,
2204 }),
2205 Self::MutationBatchTooManyItems => {
2206 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2207 boundary: diagnostic_code::RuntimeBoundaryCode::MutationBatchTooManyItems,
2208 })
2209 }
2210 Self::MutationBatchStagedBytesExceeded => {
2211 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2212 boundary:
2213 diagnostic_code::RuntimeBoundaryCode::MutationBatchStagedBytesExceeded,
2214 })
2215 }
2216 Self::MutationBatchResultBytesExceeded => {
2217 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2218 boundary:
2219 diagnostic_code::RuntimeBoundaryCode::MutationBatchResultBytesExceeded,
2220 })
2221 }
2222 Self::MutationBatchEntityMismatch => {
2223 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2224 boundary: diagnostic_code::RuntimeBoundaryCode::MutationBatchEntityMismatch,
2225 })
2226 }
2227 Self::MutationBatchDuplicateKey => {
2228 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2229 boundary: diagnostic_code::RuntimeBoundaryCode::MutationBatchDuplicateKey,
2230 })
2231 }
2232 Self::MutationManagedTimestampRegression => {
2233 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2234 boundary:
2235 diagnostic_code::RuntimeBoundaryCode::MutationManagedTimestampRegression,
2236 })
2237 }
2238 Self::ConstraintViolation { diagnostic }
2239 | Self::ConstraintActivationWriteBlocked { diagnostic } => {
2240 diagnostic.error_code().diagnostic_detail()
2241 }
2242 Self::AcceptedRowConstraintProgramCorrupt => {
2243 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2244 boundary:
2245 diagnostic_code::RuntimeBoundaryCode::AcceptedRowConstraintProgramCorrupt,
2246 })
2247 }
2248 }
2249 }
2250}
2251
2252impl RecoveryErrorDetail {
2253 #[must_use]
2255 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2256 match self {
2257 Self::UnsupportedFormatVersion { .. } => {
2258 diagnostic_code::DiagnosticCode::RuntimeIncompatiblePersistedFormat
2259 }
2260 Self::MalformedFormatMarker { .. } => {
2261 diagnostic_code::DiagnosticCode::RuntimeCorruption
2262 }
2263 }
2264 }
2265
2266 #[must_use]
2268 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2269 let kind = match self {
2270 Self::UnsupportedFormatVersion { .. } => {
2271 diagnostic_code::RuntimeErrorKind::IncompatiblePersistedFormat
2272 }
2273 Self::MalformedFormatMarker { .. } => diagnostic_code::RuntimeErrorKind::Corruption,
2274 };
2275
2276 Some(diagnostic_code::DiagnosticDetail::RuntimeKind { kind })
2277 }
2278}
2279
2280impl SerializeErrorDetail {
2281 #[must_use]
2283 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2284 match self {
2285 Self::PersistedRowLayoutOutsideAcceptedWindow | Self::PersistedRowSlotCountMismatch => {
2286 diagnostic_code::DiagnosticCode::RuntimeCorruption
2287 }
2288 }
2289 }
2290
2291 #[must_use]
2293 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2294 let boundary = match self {
2295 Self::PersistedRowLayoutOutsideAcceptedWindow => {
2296 diagnostic_code::RuntimeBoundaryCode::PersistedRowLayoutOutsideAcceptedWindow
2297 }
2298 Self::PersistedRowSlotCountMismatch => {
2299 diagnostic_code::RuntimeBoundaryCode::PersistedRowSlotCountMismatch
2300 }
2301 };
2302
2303 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary { boundary })
2304 }
2305}
2306
2307impl StoreError {
2308 #[must_use]
2310 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2311 match self {
2312 Self::NotFound => diagnostic_code::DiagnosticCode::StoreNotFound,
2313 Self::Corrupt => diagnostic_code::DiagnosticCode::StoreCorruption,
2314 Self::InvariantViolation => diagnostic_code::DiagnosticCode::StoreInvariantViolation,
2315 Self::SchemaDdlPublicationRaceLost
2316 | Self::SchemaDdlRewriteRequiresMigration
2317 | Self::SchemaRowLayoutVersionExhausted
2318 | Self::SchemaTransitionBudgetExceeded { .. } => {
2319 diagnostic_code::DiagnosticCode::SchemaDdlAdmission
2320 }
2321 Self::JournalMutationRevisionExhausted | Self::SchemaGeneratedFieldAfterDdlField => {
2322 diagnostic_code::DiagnosticCode::RuntimeUnsupported
2323 }
2324 Self::SchemaGeneratedConstraintActivationStale => {
2325 diagnostic_code::DiagnosticCode::RuntimeConflict
2326 }
2327 Self::SchemaMigration { reason } => reason.diagnostic_code(),
2328 }
2329 }
2330
2331 #[must_use]
2333 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2334 match self {
2335 Self::SchemaDdlPublicationRaceLost => {
2336 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2337 reason: diagnostic_code::SchemaDdlAdmissionCode::PublicationRaceLost,
2338 })
2339 }
2340 Self::SchemaDdlRewriteRequiresMigration => {
2341 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2342 reason: diagnostic_code::SchemaDdlAdmissionCode::SchemaRewriteRequiresMigration,
2343 })
2344 }
2345 Self::SchemaMigration { reason } => {
2346 Some(diagnostic_code::DiagnosticDetail::SchemaMigration { reason: *reason })
2347 }
2348 Self::SchemaRowLayoutVersionExhausted => {
2349 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2350 reason: diagnostic_code::SchemaDdlAdmissionCode::RowLayoutVersionExhausted,
2351 })
2352 }
2353 Self::JournalMutationRevisionExhausted => {
2354 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2355 boundary:
2356 diagnostic_code::RuntimeBoundaryCode::JournalMutationRevisionExhausted,
2357 })
2358 }
2359 Self::SchemaTransitionBudgetExceeded { .. } => {
2360 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2361 reason: diagnostic_code::SchemaDdlAdmissionCode::SchemaTransitionBudgetExceeded,
2362 })
2363 }
2364 Self::SchemaGeneratedFieldAfterDdlField => {
2365 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2366 boundary: diagnostic_code::RuntimeBoundaryCode::GeneratedFieldAfterDdlField,
2367 })
2368 }
2369 Self::SchemaGeneratedConstraintActivationStale => {
2370 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2371 boundary:
2372 diagnostic_code::RuntimeBoundaryCode::GeneratedConstraintActivationStale,
2373 })
2374 }
2375 Self::NotFound | Self::Corrupt | Self::InvariantViolation => None,
2376 }
2377 }
2378}
2379
2380impl QueryErrorDetail {
2381 #[must_use]
2383 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2384 match self {
2385 Self::NumericOverflow => diagnostic_code::DiagnosticCode::QueryNumericOverflow,
2386 Self::NumericNotRepresentable => {
2387 diagnostic_code::DiagnosticCode::QueryNumericNotRepresentable
2388 }
2389 Self::UnsupportedSqlFeature { .. } => {
2390 diagnostic_code::DiagnosticCode::QueryUnsupportedSqlFeature
2391 }
2392 Self::SqlLowering { .. } => diagnostic_code::DiagnosticCode::QueryUnsupportedSqlFeature,
2393 Self::UnsupportedProjection { .. } => {
2394 diagnostic_code::DiagnosticCode::QueryUnsupportedProjection
2395 }
2396 Self::UnknownAggregateTargetField => {
2397 diagnostic_code::DiagnosticCode::QueryUnknownAggregateTargetField
2398 }
2399 Self::ResultShapeMismatch { .. } => {
2400 diagnostic_code::DiagnosticCode::QueryResultShapeMismatch
2401 }
2402 Self::QueryReadAdmission { .. } => diagnostic_code::DiagnosticCode::QueryReadAdmission,
2403 Self::SqlSurfaceMismatch { .. } => {
2404 diagnostic_code::DiagnosticCode::QuerySqlSurfaceMismatch
2405 }
2406 Self::SqlWriteBoundary { .. } => diagnostic_code::DiagnosticCode::QuerySqlWriteBoundary,
2407 Self::SchemaDdlAdmission { .. } => diagnostic_code::DiagnosticCode::SchemaDdlAdmission,
2408 Self::StaleSchemaRevision => diagnostic_code::DiagnosticCode::RuntimeConflict,
2409 }
2410 }
2411
2412 #[must_use]
2414 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2415 match self {
2416 Self::UnsupportedSqlFeature { feature } => {
2417 Some(diagnostic_code::DiagnosticDetail::UnsupportedSqlFeature { feature: *feature })
2418 }
2419 Self::SqlLowering { reason } => {
2420 Some(diagnostic_code::DiagnosticDetail::SqlLowering { reason: *reason })
2421 }
2422 Self::UnsupportedProjection { reason } => {
2423 Some(diagnostic_code::DiagnosticDetail::QueryProjection { reason: *reason })
2424 }
2425 Self::ResultShapeMismatch { reason } => {
2426 Some(diagnostic_code::DiagnosticDetail::QueryResultShape { reason: *reason })
2427 }
2428 Self::QueryReadAdmission { reason } => {
2429 Some(diagnostic_code::DiagnosticDetail::QueryReadAdmission { reason: *reason })
2430 }
2431 Self::SqlSurfaceMismatch { mismatch } => {
2432 Some(diagnostic_code::DiagnosticDetail::SqlSurfaceMismatch {
2433 mismatch: *mismatch,
2434 })
2435 }
2436 Self::SqlWriteBoundary { boundary } => {
2437 Some(diagnostic_code::DiagnosticDetail::SqlWriteBoundary {
2438 boundary: *boundary,
2439 })
2440 }
2441 Self::SchemaDdlAdmission { error } => {
2442 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2443 reason: error.diagnostic_code(),
2444 })
2445 }
2446 Self::NumericOverflow
2447 | Self::NumericNotRepresentable
2448 | Self::UnknownAggregateTargetField
2449 | Self::StaleSchemaRevision => None,
2450 }
2451 }
2452}
2453
2454impl SchemaDdlAdmissionError {
2455 #[must_use]
2457 pub const fn diagnostic_code(&self) -> diagnostic_code::SchemaDdlAdmissionCode {
2458 match self {
2459 Self::MissingExpectedSchemaVersion => {
2460 diagnostic_code::SchemaDdlAdmissionCode::MissingExpectedSchemaVersion
2461 }
2462 Self::MissingNextSchemaVersion => {
2463 diagnostic_code::SchemaDdlAdmissionCode::MissingNextSchemaVersion
2464 }
2465 Self::StaleExpectedSchemaVersion => {
2466 diagnostic_code::SchemaDdlAdmissionCode::StaleExpectedSchemaVersion
2467 }
2468 Self::InvalidExpectedSchemaVersion => {
2469 diagnostic_code::SchemaDdlAdmissionCode::InvalidExpectedSchemaVersion
2470 }
2471 Self::InvalidNextSchemaVersion => {
2472 diagnostic_code::SchemaDdlAdmissionCode::InvalidNextSchemaVersion
2473 }
2474 Self::AcceptedSchemaChangeWithoutVersionBump => {
2475 diagnostic_code::SchemaDdlAdmissionCode::AcceptedSchemaChangeWithoutVersionBump
2476 }
2477 Self::EmptyVersionBump => diagnostic_code::SchemaDdlAdmissionCode::EmptyVersionBump,
2478 Self::VersionGap => diagnostic_code::SchemaDdlAdmissionCode::VersionGap,
2479 Self::VersionRollback => diagnostic_code::SchemaDdlAdmissionCode::VersionRollback,
2480 Self::FingerprintMethodMismatch => {
2481 diagnostic_code::SchemaDdlAdmissionCode::FingerprintMethodMismatch
2482 }
2483 Self::UnsupportedTransitionClass => {
2484 diagnostic_code::SchemaDdlAdmissionCode::UnsupportedTransitionClass
2485 }
2486 Self::PhysicalRunnerMissing => {
2487 diagnostic_code::SchemaDdlAdmissionCode::PhysicalRunnerMissing
2488 }
2489 Self::ValidationFailed => diagnostic_code::SchemaDdlAdmissionCode::ValidationFailed,
2490 Self::PublicationRaceLost => {
2491 diagnostic_code::SchemaDdlAdmissionCode::PublicationRaceLost
2492 }
2493 Self::InvalidAddColumnDefault => {
2494 diagnostic_code::SchemaDdlAdmissionCode::InvalidAddColumnDefault
2495 }
2496 Self::InvalidAlterColumnDefault => {
2497 diagnostic_code::SchemaDdlAdmissionCode::InvalidAlterColumnDefault
2498 }
2499 Self::GeneratedIndexDropRejected => {
2500 diagnostic_code::SchemaDdlAdmissionCode::GeneratedIndexDropRejected
2501 }
2502 Self::SchemaRewriteRequiresMigration => {
2503 diagnostic_code::SchemaDdlAdmissionCode::SchemaRewriteRequiresMigration
2504 }
2505 Self::SchemaTransitionBudgetExceeded { .. } => {
2506 diagnostic_code::SchemaDdlAdmissionCode::SchemaTransitionBudgetExceeded
2507 }
2508 Self::GeneratedFieldDefaultChangeRejected => {
2509 diagnostic_code::SchemaDdlAdmissionCode::GeneratedFieldDefaultChangeRejected
2510 }
2511 Self::GeneratedFieldNullabilityChangeRejected => {
2512 diagnostic_code::SchemaDdlAdmissionCode::GeneratedFieldNullabilityChangeRejected
2513 }
2514 Self::RowLayoutVersionExhausted => {
2515 diagnostic_code::SchemaDdlAdmissionCode::RowLayoutVersionExhausted
2516 }
2517 }
2518 }
2519}
2520
2521#[repr(u8)]
2528#[derive(Clone, Copy, Eq, PartialEq)]
2529pub enum ErrorClass {
2530 Corruption,
2531 IncompatiblePersistedFormat,
2532 NotFound,
2533 Internal,
2534 Conflict,
2535 Unsupported,
2536 InvariantViolation,
2537}
2538
2539impl ErrorClass {
2540 #[must_use]
2542 pub const fn diagnostic_code(self, origin: ErrorOrigin) -> diagnostic_code::DiagnosticCode {
2543 match self {
2544 Self::Corruption if matches!(origin, ErrorOrigin::Store) => {
2545 diagnostic_code::DiagnosticCode::StoreCorruption
2546 }
2547 Self::Corruption => diagnostic_code::DiagnosticCode::RuntimeCorruption,
2548 Self::IncompatiblePersistedFormat => {
2549 diagnostic_code::DiagnosticCode::RuntimeIncompatiblePersistedFormat
2550 }
2551 Self::NotFound if matches!(origin, ErrorOrigin::Store) => {
2552 diagnostic_code::DiagnosticCode::StoreNotFound
2553 }
2554 Self::NotFound => diagnostic_code::DiagnosticCode::RuntimeNotFound,
2555 Self::Internal => diagnostic_code::DiagnosticCode::RuntimeInternal,
2556 Self::Conflict => diagnostic_code::DiagnosticCode::RuntimeConflict,
2557 Self::Unsupported if matches!(origin, ErrorOrigin::Cursor) => {
2558 diagnostic_code::DiagnosticCode::QueryInvalidContinuationCursor
2559 }
2560 Self::Unsupported => diagnostic_code::DiagnosticCode::RuntimeUnsupported,
2561 Self::InvariantViolation if matches!(origin, ErrorOrigin::Store) => {
2562 diagnostic_code::DiagnosticCode::StoreInvariantViolation
2563 }
2564 Self::InvariantViolation => diagnostic_code::DiagnosticCode::RuntimeInvariantViolation,
2565 }
2566 }
2567}
2568
2569impl fmt::Debug for ErrorClass {
2570 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2571 write!(f, "{}", *self as u8)
2572 }
2573}
2574
2575#[repr(u8)]
2582#[derive(Clone, Copy, Eq, PartialEq)]
2583pub enum ErrorOrigin {
2584 Serialize,
2585 Store,
2586 Index,
2587 Identity,
2588 Query,
2589 Planner,
2590 Cursor,
2591 Recovery,
2592 Response,
2593 Executor,
2594 Interface,
2595}
2596
2597impl ErrorOrigin {
2598 #[must_use]
2600 pub const fn diagnostic_origin(self) -> diagnostic_code::ErrorOrigin {
2601 match self {
2602 Self::Serialize => diagnostic_code::ErrorOrigin::Serialize,
2603 Self::Store => diagnostic_code::ErrorOrigin::Store,
2604 Self::Index => diagnostic_code::ErrorOrigin::Index,
2605 Self::Identity => diagnostic_code::ErrorOrigin::Identity,
2606 Self::Query => diagnostic_code::ErrorOrigin::Query,
2607 Self::Planner => diagnostic_code::ErrorOrigin::Planner,
2608 Self::Cursor => diagnostic_code::ErrorOrigin::Cursor,
2609 Self::Recovery => diagnostic_code::ErrorOrigin::Recovery,
2610 Self::Response => diagnostic_code::ErrorOrigin::Response,
2611 Self::Executor => diagnostic_code::ErrorOrigin::Executor,
2612 Self::Interface => diagnostic_code::ErrorOrigin::Interface,
2613 }
2614 }
2615}
2616
2617impl fmt::Debug for ErrorOrigin {
2618 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2619 write!(f, "{}", *self as u8)
2620 }
2621}