1#[cfg(test)]
9mod tests;
10
11use icydb_diagnostic_code as diagnostic_code;
12use std::fmt;
13
14pub(crate) const COMPACT_QUERY_DIAGNOSTIC_MESSAGE: &str = "query diagnostic";
15const COMPACT_RUNTIME_DIAGNOSTIC_MESSAGE: &str = "runtime diagnostic";
16const COMPACT_STORE_DIAGNOSTIC_MESSAGE: &str = "store diagnostic";
17const COMPACT_INDEX_DIAGNOSTIC_MESSAGE: &str = "index diagnostic";
18const COMPACT_SERIALIZE_DIAGNOSTIC_MESSAGE: &str = "serialize diagnostic";
19const COMPACT_IDENTITY_DIAGNOSTIC_MESSAGE: &str = "identity diagnostic";
20
21const fn compact_message_for(_class: ErrorClass, origin: ErrorOrigin) -> &'static str {
22 match origin {
23 ErrorOrigin::Serialize => COMPACT_SERIALIZE_DIAGNOSTIC_MESSAGE,
24 ErrorOrigin::Store => COMPACT_STORE_DIAGNOSTIC_MESSAGE,
25 ErrorOrigin::Index => COMPACT_INDEX_DIAGNOSTIC_MESSAGE,
26 ErrorOrigin::Identity => COMPACT_IDENTITY_DIAGNOSTIC_MESSAGE,
27 ErrorOrigin::Query | ErrorOrigin::Planner | ErrorOrigin::Response => {
28 COMPACT_QUERY_DIAGNOSTIC_MESSAGE
29 }
30 ErrorOrigin::Cursor
31 | ErrorOrigin::Recovery
32 | ErrorOrigin::Executor
33 | ErrorOrigin::Interface => COMPACT_RUNTIME_DIAGNOSTIC_MESSAGE,
34 }
35}
36
37pub struct InternalError {
138 pub(crate) class: ErrorClass,
139 pub(crate) origin: ErrorOrigin,
140
141 pub(crate) detail: Option<ErrorDetail>,
144}
145
146#[expect(
147 clippy::missing_const_for_fn,
148 reason = "internal error constructors stay non-const so compact diagnostic construction does not force const churn across subsystem helper seams"
149)]
150impl InternalError {
151 #[must_use]
155 #[cold]
156 #[inline(never)]
157 pub fn new(class: ErrorClass, origin: ErrorOrigin) -> Self {
158 let detail = match (class, origin) {
159 (ErrorClass::Corruption, ErrorOrigin::Store) => {
160 Some(ErrorDetail::Store(StoreError::Corrupt))
161 }
162 (ErrorClass::InvariantViolation, ErrorOrigin::Store) => {
163 Some(ErrorDetail::Store(StoreError::InvariantViolation))
164 }
165 _ => None,
166 };
167
168 Self {
169 class,
170 origin,
171 detail,
172 }
173 }
174
175 #[must_use]
177 pub const fn class(&self) -> ErrorClass {
178 self.class
179 }
180
181 #[must_use]
183 pub const fn origin(&self) -> ErrorOrigin {
184 self.origin
185 }
186
187 #[must_use]
189 pub const fn message(&self) -> &'static str {
190 compact_message_for(self.class, self.origin)
191 }
192
193 #[must_use]
195 pub const fn detail(&self) -> Option<&ErrorDetail> {
196 self.detail.as_ref()
197 }
198
199 #[must_use]
201 pub fn diagnostic(&self) -> diagnostic_code::Diagnostic {
202 diagnostic_code::Diagnostic::new(
203 self.diagnostic_code(),
204 self.origin.diagnostic_origin(),
205 self.detail
206 .as_ref()
207 .and_then(ErrorDetail::diagnostic_detail),
208 )
209 }
210
211 #[must_use]
213 pub fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
214 self.detail.as_ref().map_or_else(
215 || self.class.diagnostic_code(self.origin),
216 ErrorDetail::diagnostic_code,
217 )
218 }
219
220 #[must_use]
222 pub fn into_message(self) -> String {
223 self.message().to_string()
224 }
225
226 #[cold]
228 #[inline(never)]
229 pub(crate) fn classified(class: ErrorClass, origin: ErrorOrigin) -> Self {
230 Self::new(class, origin)
231 }
232
233 #[cold]
237 #[inline(never)]
238 pub(crate) fn with_origin(self, origin: ErrorOrigin) -> Self {
239 Self::classified(self.class, origin)
240 }
241
242 #[cold]
244 #[inline(never)]
245 pub(crate) fn index_invariant() -> Self {
246 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Index)
247 }
248
249 pub(crate) fn index_key_field_count_exceeds_max(
251 _index_name: &str,
252 _field_count: usize,
253 _max_fields: usize,
254 ) -> Self {
255 Self::index_invariant()
256 }
257
258 pub(crate) fn index_key_item_field_missing_on_entity_model(_field: &str) -> Self {
260 Self::index_invariant()
261 }
262
263 pub(crate) fn index_key_item_field_missing_on_lookup_row(_field: &str) -> Self {
265 Self::index_invariant()
266 }
267
268 pub(crate) fn index_expression_source_type_mismatch(
270 _index_name: &str,
271 _expression: impl Sized,
272 _expected: impl Sized,
273 _source_label: &str,
274 ) -> Self {
275 Self::index_invariant()
276 }
277
278 #[cold]
281 #[inline(never)]
282 pub(crate) fn planner_executor_invariant() -> Self {
283 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Planner)
284 }
285
286 #[cold]
289 #[inline(never)]
290 pub(crate) fn query_executor_invariant() -> Self {
291 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Query)
292 }
293
294 #[cold]
297 #[inline(never)]
298 pub(crate) fn cursor_executor_invariant() -> Self {
299 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Cursor)
300 }
301
302 #[cold]
304 #[inline(never)]
305 pub(crate) fn executor_invariant() -> Self {
306 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Executor)
307 }
308
309 #[cold]
311 #[inline(never)]
312 pub(crate) fn executor_conflict() -> Self {
313 Self::new(ErrorClass::Conflict, 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_entity_primary_key_missing(
332 _entity_path: &str,
333 _field_name: &str,
334 ) -> Self {
335 Self::executor_invariant()
336 }
337
338 pub(crate) fn mutation_entity_primary_key_invalid_value(
340 _entity_path: &str,
341 _field_name: &str,
342 _value: &crate::value::Value,
343 ) -> Self {
344 Self::executor_invariant()
345 }
346
347 pub(crate) fn mutation_entity_primary_key_type_mismatch(
349 _entity_path: &str,
350 _field_name: &str,
351 _value: &crate::value::Value,
352 ) -> Self {
353 Self::executor_invariant()
354 }
355
356 pub(crate) fn mutation_entity_primary_key_mismatch(
358 _entity_path: &str,
359 _field_name: &str,
360 _field_value: &crate::value::Value,
361 _identity_key: &crate::value::Value,
362 ) -> Self {
363 Self::executor_invariant()
364 }
365
366 pub(crate) fn mutation_entity_field_missing(
368 _entity_path: &str,
369 _field_name: &str,
370 _indexed: bool,
371 ) -> Self {
372 Self::executor_invariant()
373 }
374
375 pub(crate) fn mutation_structural_patch_required_field_missing(
377 entity_path: &str,
378 field_name: &str,
379 ) -> Self {
380 Self::mutation_required_field_missing(entity_path, field_name)
381 }
382
383 pub(crate) fn mutation_entity_field_type_mismatch(
385 _entity_path: &str,
386 _field_name: &str,
387 _value: &crate::value::Value,
388 ) -> Self {
389 Self::executor_invariant()
390 }
391
392 pub(crate) fn mutation_database_owned_field_explicit(
394 _entity_path: &str,
395 _field_name: &str,
396 ) -> Self {
397 Self::executor_unsupported()
398 }
399
400 pub(crate) fn mutation_sanitizer_protected_field_changed(
402 _entity_path: &str,
403 _field_name: &str,
404 ) -> Self {
405 Self::executor_unsupported()
406 }
407
408 #[must_use]
410 pub fn mutation_required_field_missing(_entity_path: &str, _field_names: &str) -> Self {
411 Self {
412 class: ErrorClass::Unsupported,
413 origin: ErrorOrigin::Executor,
414 detail: Some(ErrorDetail::Executor(
415 ExecutorErrorDetail::MutationRequiredFieldMissing,
416 )),
417 }
418 }
419
420 pub(crate) fn mutation_structural_after_image_invalid(
425 _entity_path: &str,
426 _data_key: impl Sized,
427 _detail: impl Sized,
428 ) -> Self {
429 Self::executor_invariant()
430 }
431
432 pub(crate) fn mutation_structural_field_unknown(_entity_path: &str, _field_name: &str) -> Self {
434 Self::executor_invariant()
435 }
436
437 pub(crate) fn mutation_decimal_scale_mismatch(
439 _entity_path: &str,
440 _field_name: &str,
441 _expected_scale: impl Sized,
442 _actual_scale: impl Sized,
443 ) -> Self {
444 Self::executor_unsupported()
445 }
446
447 pub(crate) fn mutation_text_max_len_exceeded(
449 _entity_path: &str,
450 _field_name: &str,
451 _max_len: impl Sized,
452 _actual_len: impl Sized,
453 ) -> Self {
454 Self::executor_unsupported()
455 }
456
457 pub(crate) fn mutation_set_field_list_required(_entity_path: &str, _field_name: &str) -> Self {
459 Self::executor_invariant()
460 }
461
462 pub(crate) fn mutation_set_field_not_canonical(_entity_path: &str, _field_name: &str) -> Self {
464 Self::executor_invariant()
465 }
466
467 pub(crate) fn mutation_map_field_map_required(_entity_path: &str, _field_name: &str) -> Self {
469 Self::executor_invariant()
470 }
471
472 pub(crate) fn mutation_map_field_entries_invalid(
474 _entity_path: &str,
475 _field_name: &str,
476 _detail: impl Sized,
477 ) -> Self {
478 Self::executor_invariant()
479 }
480
481 pub(crate) fn mutation_map_field_entries_not_canonical(
483 _entity_path: &str,
484 _field_name: &str,
485 ) -> Self {
486 Self::executor_invariant()
487 }
488
489 pub(crate) fn scalar_page_cursor_boundary_order_required() -> Self {
491 Self::query_executor_invariant()
492 }
493
494 pub(crate) fn scalar_page_cursor_boundary_after_ordering_required() -> Self {
496 Self::query_executor_invariant()
497 }
498
499 pub(crate) fn scalar_page_pagination_after_ordering_required() -> Self {
501 Self::query_executor_invariant()
502 }
503
504 pub(crate) fn load_executor_load_plan_required() -> Self {
506 Self::query_executor_invariant()
507 }
508
509 pub(crate) fn delete_executor_grouped_unsupported() -> Self {
511 Self::executor_unsupported()
512 }
513
514 pub(crate) fn delete_executor_delete_plan_required() -> Self {
516 Self::query_executor_invariant()
517 }
518
519 pub(crate) fn aggregate_fold_mode_terminal_contract_required() -> Self {
521 Self::query_executor_invariant()
522 }
523
524 pub(crate) fn fast_stream_route_kind_request_match_required() -> Self {
526 Self::query_executor_invariant()
527 }
528
529 pub(crate) fn secondary_index_prefix_spec_required() -> Self {
531 Self::query_executor_invariant()
532 }
533
534 pub(crate) fn index_range_limit_spec_required() -> Self {
536 Self::query_executor_invariant()
537 }
538
539 pub(crate) fn mutation_atomic_save_duplicate_key(_entity_path: &str, _key: impl Sized) -> Self {
541 Self::executor_conflict()
542 }
543
544 pub(crate) fn mutation_index_store_generation_changed(
546 _expected_generation: u64,
547 _observed_generation: u64,
548 ) -> Self {
549 Self::executor_invariant()
550 }
551
552 #[cold]
554 #[inline(never)]
555 pub(crate) fn planner_invariant() -> Self {
556 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Planner)
557 }
558
559 pub(crate) fn query_invalid_logical_plan() -> Self {
561 Self::planner_invariant()
562 }
563
564 pub(crate) fn store_invariant() -> Self {
566 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Store)
567 }
568
569 pub(crate) fn duplicate_runtime_hooks_for_entity_tag(
571 _entity_tag: crate::types::EntityTag,
572 ) -> Self {
573 Self::store_invariant()
574 }
575
576 pub(crate) fn duplicate_runtime_hooks_for_entity_path(_entity_path: &str) -> Self {
578 Self::store_invariant()
579 }
580
581 #[cold]
583 #[inline(never)]
584 pub(crate) fn store_internal() -> Self {
585 Self::new(ErrorClass::Internal, ErrorOrigin::Store)
586 }
587
588 pub(crate) fn commit_memory_id_unconfigured() -> Self {
590 Self::store_internal()
591 }
592
593 pub(crate) fn commit_memory_id_mismatch(_cached_id: u8, _configured_id: u8) -> Self {
595 Self::store_internal()
596 }
597
598 pub(crate) fn commit_memory_stable_key_mismatch(
600 _cached_key: &str,
601 _configured_key: &str,
602 ) -> Self {
603 Self::store_internal()
604 }
605
606 pub(crate) fn recovery_unsupported_database_format(found: Option<u16>, required: u16) -> Self {
608 Self {
609 class: ErrorClass::IncompatiblePersistedFormat,
610 origin: ErrorOrigin::Recovery,
611 detail: Some(ErrorDetail::Recovery(
612 RecoveryErrorDetail::UnsupportedFormatVersion { found, required },
613 )),
614 }
615 }
616
617 pub(crate) fn recovery_malformed_database_format_marker(
619 reason: RecoveryFormatMarkerError,
620 ) -> Self {
621 Self {
622 class: ErrorClass::Corruption,
623 origin: ErrorOrigin::Recovery,
624 detail: Some(ErrorDetail::Recovery(
625 RecoveryErrorDetail::MalformedFormatMarker { reason },
626 )),
627 }
628 }
629
630 pub(crate) fn recovery_database_format_control_unavailable() -> Self {
632 Self::new(ErrorClass::Internal, ErrorOrigin::Recovery)
633 }
634
635 pub(crate) fn commit_control_memory_growth_failed() -> Self {
637 Self::store_internal()
638 }
639
640 #[cfg(not(test))]
642 pub(crate) fn database_format_memory_registration_failed(_err: impl Sized) -> Self {
643 Self::store_internal()
644 }
645
646 pub(crate) fn delete_rollback_row_required() -> Self {
648 Self::store_internal()
649 }
650
651 pub(crate) fn recovery_integrity_validation_failed(
653 _missing_index_entries: u64,
654 _divergent_index_entries: u64,
655 _orphan_index_references: u64,
656 ) -> Self {
657 Self::store_corruption()
658 }
659
660 #[cold]
662 #[inline(never)]
663 pub(crate) fn index_internal() -> Self {
664 Self::new(ErrorClass::Internal, ErrorOrigin::Index)
665 }
666
667 pub(crate) fn structural_index_removal_entity_key_required() -> Self {
669 Self::index_internal()
670 }
671
672 pub(crate) fn structural_index_insertion_entity_key_required() -> Self {
674 Self::index_internal()
675 }
676
677 pub(crate) fn index_commit_op_old_entity_key_required() -> Self {
679 Self::index_internal()
680 }
681
682 pub(crate) fn index_commit_op_new_entity_key_required() -> Self {
684 Self::index_internal()
685 }
686
687 #[cfg(test)]
689 pub(crate) fn query_internal() -> Self {
690 Self::new(ErrorClass::Internal, ErrorOrigin::Query)
691 }
692
693 #[cold]
695 #[inline(never)]
696 pub(crate) fn query_unsupported() -> Self {
697 Self::new(ErrorClass::Unsupported, ErrorOrigin::Query)
698 }
699
700 #[cold]
703 #[inline(never)]
704 pub(crate) fn query_stale_accepted_schema_revision(
705 _expected_revision: u64,
706 _current_revision: Option<u64>,
707 ) -> Self {
708 Self {
709 class: ErrorClass::Conflict,
710 origin: ErrorOrigin::Query,
711 detail: Some(ErrorDetail::Query(QueryErrorDetail::StaleSchemaRevision)),
712 }
713 }
714
715 #[cold]
717 #[inline(never)]
718 #[cfg(feature = "sql")]
719 pub(crate) fn query_schema_ddl_admission(error: SchemaDdlAdmissionError) -> Self {
720 Self {
721 class: ErrorClass::Unsupported,
722 origin: ErrorOrigin::Query,
723 detail: Some(ErrorDetail::Query(QueryErrorDetail::SchemaDdlAdmission {
724 error,
725 })),
726 }
727 }
728
729 #[cold]
731 #[inline(never)]
732 pub(crate) fn query_numeric_overflow() -> Self {
733 Self {
734 class: ErrorClass::Unsupported,
735 origin: ErrorOrigin::Query,
736 detail: Some(ErrorDetail::Query(QueryErrorDetail::NumericOverflow)),
737 }
738 }
739
740 #[cold]
743 #[inline(never)]
744 pub(crate) fn query_numeric_not_representable() -> Self {
745 Self {
746 class: ErrorClass::Unsupported,
747 origin: ErrorOrigin::Query,
748 detail: Some(ErrorDetail::Query(
749 QueryErrorDetail::NumericNotRepresentable,
750 )),
751 }
752 }
753
754 #[cold]
756 #[inline(never)]
757 pub(crate) fn serialize_internal() -> Self {
758 Self::new(ErrorClass::Internal, ErrorOrigin::Serialize)
759 }
760
761 pub(crate) fn persisted_row_encode_failed(_detail: impl Sized) -> Self {
763 Self::persisted_row_encode_internal()
764 }
765
766 pub(crate) fn persisted_row_encode_internal() -> Self {
768 Self::serialize_internal()
769 }
770
771 pub(crate) fn persisted_row_field_encode_failed(field_name: &str, _detail: impl Sized) -> Self {
773 Self::persisted_row_field_encode_internal(field_name)
774 }
775
776 pub(crate) fn persisted_row_field_encode_internal(_field_name: &str) -> Self {
778 Self::persisted_row_encode_internal()
779 }
780
781 pub(crate) fn bytes_field_value_encode_failed(_detail: impl Sized) -> Self {
783 Self::serialize_internal()
784 }
785
786 #[cold]
788 #[inline(never)]
789 pub(crate) fn store_corruption() -> Self {
790 Self::new(ErrorClass::Corruption, ErrorOrigin::Store)
791 }
792
793 pub(crate) fn commit_corruption() -> Self {
795 Self::store_corruption()
796 }
797
798 pub(crate) fn commit_component_corruption() -> Self {
800 Self::commit_corruption()
801 }
802
803 pub(crate) fn commit_id_generation_failed() -> Self {
805 Self::store_internal()
806 }
807
808 pub(crate) fn commit_marker_payload_exceeds_u32_length_limit() -> Self {
810 Self::store_unsupported()
811 }
812
813 pub(crate) fn commit_component_length_invalid() -> Self {
815 Self::commit_corruption()
816 }
817
818 pub(crate) fn commit_marker_exceeds_max_size() -> Self {
820 Self::commit_corruption()
821 }
822
823 pub(crate) fn commit_control_slot_exceeds_max_size() -> Self {
825 Self::store_unsupported()
826 }
827
828 pub(crate) fn commit_control_slot_marker_bytes_exceed_u32_length_limit() -> Self {
830 Self::store_unsupported()
831 }
832
833 pub(crate) fn startup_index_rebuild_invalid_data_key() -> Self {
835 Self::store_corruption()
836 }
837
838 #[cold]
840 #[inline(never)]
841 pub(crate) fn index_corruption() -> Self {
842 Self::new(ErrorClass::Corruption, ErrorOrigin::Index)
843 }
844
845 pub(crate) fn index_unique_validation_corruption() -> Self {
847 Self::index_plan_index_corruption()
848 }
849
850 pub(crate) fn structural_index_entry_corruption() -> Self {
852 Self::index_plan_index_corruption()
853 }
854
855 pub(crate) fn index_unique_validation_entity_key_required() -> Self {
857 Self::index_invariant()
858 }
859
860 pub(crate) fn index_unique_validation_row_deserialize_failed() -> Self {
862 Self::index_plan_serialize_corruption()
863 }
864
865 pub(crate) fn index_unique_validation_primary_key_decode_failed() -> Self {
867 Self::index_plan_serialize_corruption()
868 }
869
870 pub(crate) fn index_unique_validation_key_rebuild_failed() -> Self {
872 Self::index_plan_serialize_corruption()
873 }
874
875 pub(crate) fn index_unique_validation_row_required() -> Self {
877 Self::index_plan_store_corruption()
878 }
879
880 pub(crate) fn index_only_predicate_component_required() -> Self {
882 Self::index_invariant()
883 }
884
885 pub(crate) fn index_scan_continuation_anchor_within_envelope_required() -> Self {
887 Self::index_invariant()
888 }
889
890 pub(crate) fn index_scan_continuation_advancement_required() -> Self {
892 Self::index_invariant()
893 }
894
895 pub(crate) fn index_scan_key_corrupted_during(
897 _context: &'static str,
898 _err: impl Sized,
899 ) -> Self {
900 Self::index_corruption()
901 }
902
903 pub(crate) fn index_projection_component_required(
905 _index_name: &str,
906 _component_index: usize,
907 ) -> Self {
908 Self::index_invariant()
909 }
910
911 pub(crate) fn index_entry_decode_failed() -> Self {
913 Self::index_corruption()
914 }
915
916 pub(crate) fn serialize_corruption() -> Self {
918 Self::new(ErrorClass::Corruption, ErrorOrigin::Serialize)
919 }
920
921 pub(crate) fn persisted_row_decode_failed(_detail: impl Sized) -> Self {
923 Self::persisted_row_decode_corruption()
924 }
925
926 pub(crate) fn persisted_row_decode_corruption() -> Self {
928 Self::serialize_corruption()
929 }
930
931 pub(crate) fn persisted_row_layout_outside_accepted_window() -> Self {
933 Self {
934 class: ErrorClass::Corruption,
935 origin: ErrorOrigin::Serialize,
936 detail: Some(ErrorDetail::Serialize(
937 SerializeErrorDetail::PersistedRowLayoutOutsideAcceptedWindow,
938 )),
939 }
940 }
941
942 pub(crate) fn persisted_row_slot_count_mismatch() -> Self {
944 Self {
945 class: ErrorClass::Corruption,
946 origin: ErrorOrigin::Serialize,
947 detail: Some(ErrorDetail::Serialize(
948 SerializeErrorDetail::PersistedRowSlotCountMismatch,
949 )),
950 }
951 }
952
953 pub(crate) fn persisted_row_field_decode_failed(field_name: &str, _detail: impl Sized) -> Self {
955 Self::persisted_row_field_decode_corruption(field_name)
956 }
957
958 pub(crate) fn persisted_row_field_decode_corruption(_field_name: &str) -> Self {
960 Self::persisted_row_decode_corruption()
961 }
962
963 pub(crate) fn persisted_row_field_kind_decode_failed(
965 field_name: &str,
966 _field_kind: impl fmt::Debug,
967 _detail: impl Sized,
968 ) -> Self {
969 Self::persisted_row_field_decode_corruption(field_name)
970 }
971
972 pub(crate) fn persisted_row_field_payload_exact_len_required(field_name: &str) -> Self {
974 Self::persisted_row_field_decode_corruption(field_name)
975 }
976
977 pub(crate) fn persisted_row_field_payload_must_be_empty(field_name: &str) -> Self {
979 Self::persisted_row_field_decode_corruption(field_name)
980 }
981
982 pub(crate) fn persisted_row_field_payload_invalid_byte(field_name: &str) -> Self {
984 Self::persisted_row_field_decode_corruption(field_name)
985 }
986
987 pub(crate) fn persisted_row_field_payload_non_finite(field_name: &str) -> Self {
989 Self::persisted_row_field_decode_corruption(field_name)
990 }
991
992 pub(crate) fn persisted_row_field_payload_out_of_range(field_name: &str) -> Self {
994 Self::persisted_row_field_decode_corruption(field_name)
995 }
996
997 pub(crate) fn persisted_row_field_text_payload_invalid_utf8(field_name: &str) -> Self {
999 Self::persisted_row_field_decode_corruption(field_name)
1000 }
1001
1002 pub(crate) fn persisted_row_slot_lookup_out_of_bounds(_model_path: &str, _slot: usize) -> Self {
1004 Self::index_invariant()
1005 }
1006
1007 pub(crate) fn persisted_row_slot_cache_lookup_out_of_bounds(
1009 _model_path: &str,
1010 _slot: usize,
1011 ) -> Self {
1012 Self::index_invariant()
1013 }
1014
1015 pub(crate) fn persisted_row_primary_key_not_primary_key_encodable(
1017 _data_key: impl fmt::Debug,
1018 _detail: impl Sized,
1019 ) -> Self {
1020 Self::persisted_row_decode_corruption()
1021 }
1022
1023 pub(crate) fn persisted_row_primary_key_slot_missing(_data_key: impl fmt::Debug) -> Self {
1025 Self::persisted_row_decode_corruption()
1026 }
1027
1028 pub(crate) fn persisted_row_key_mismatch() -> Self {
1030 Self::store_corruption()
1031 }
1032
1033 pub(crate) fn persisted_row_declared_field_missing(field_name: &str) -> Self {
1035 Self::persisted_row_field_decode_corruption(field_name)
1036 }
1037
1038 pub(crate) fn data_key_entity_mismatch() -> Self {
1040 Self::store_corruption()
1041 }
1042
1043 pub(crate) fn reverse_index_ordinal_overflow(
1045 _source_path: &str,
1046 _field_name: &str,
1047 _target_path: &str,
1048 _detail: impl Sized,
1049 ) -> Self {
1050 Self::index_internal()
1051 }
1052
1053 pub(crate) fn reverse_index_entry_corrupted(
1055 _source_path: &str,
1056 _field_name: &str,
1057 _target_path: &str,
1058 _index_key: impl fmt::Debug,
1059 _detail: impl Sized,
1060 ) -> Self {
1061 Self::index_corruption()
1062 }
1063
1064 pub(crate) fn relation_target_store_missing(
1066 _source_path: &str,
1067 _field_name: &str,
1068 _target_path: &str,
1069 _store_path: &str,
1070 _detail: impl Sized,
1071 ) -> Self {
1072 Self::executor_internal()
1073 }
1074
1075 pub(crate) fn relation_target_key_decode_failed(
1077 _context_label: &str,
1078 _source_path: &str,
1079 _field_name: &str,
1080 _target_path: &str,
1081 _detail: impl Sized,
1082 ) -> Self {
1083 Self::identity_corruption()
1084 }
1085
1086 pub(crate) fn relation_target_entity_mismatch(
1088 _context_label: &str,
1089 _source_path: &str,
1090 _field_name: &str,
1091 _target_path: &str,
1092 _target_entity_name: &str,
1093 _expected_tag: impl Sized,
1094 _actual_tag: impl Sized,
1095 ) -> Self {
1096 Self::store_corruption()
1097 }
1098
1099 pub(crate) fn relation_source_row_decode_failed(
1101 _source_path: &str,
1102 _field_name: &str,
1103 _target_path: &str,
1104 _detail: impl Sized,
1105 ) -> Self {
1106 Self::persisted_row_decode_corruption()
1107 }
1108
1109 pub(crate) fn relation_source_row_unsupported_scalar_relation_key(
1111 _source_path: &str,
1112 _field_name: &str,
1113 _target_path: &str,
1114 ) -> Self {
1115 Self::persisted_row_decode_corruption()
1116 }
1117
1118 pub(crate) fn relation_source_row_unsupported_key_kind(_field_kind: impl fmt::Debug) -> Self {
1120 Self::persisted_row_decode_corruption()
1121 }
1122
1123 pub(crate) fn reverse_index_relation_target_decode_invariant_violated(
1125 _source_path: &str,
1126 _field_name: &str,
1127 _target_path: &str,
1128 ) -> Self {
1129 Self::executor_internal()
1130 }
1131
1132 pub(crate) fn bytes_covering_component_payload_empty() -> Self {
1134 Self::index_corruption()
1135 }
1136
1137 pub(crate) fn bytes_covering_bool_payload_truncated() -> Self {
1139 Self::index_corruption()
1140 }
1141
1142 pub(crate) fn bytes_covering_component_payload_invalid_length() -> Self {
1144 Self::index_corruption()
1145 }
1146
1147 pub(crate) fn bytes_covering_bool_payload_invalid_value() -> Self {
1149 Self::index_corruption()
1150 }
1151
1152 pub(crate) fn bytes_covering_text_payload_invalid_terminator() -> Self {
1154 Self::index_corruption()
1155 }
1156
1157 pub(crate) fn bytes_covering_text_payload_trailing_bytes() -> Self {
1159 Self::index_corruption()
1160 }
1161
1162 pub(crate) fn bytes_covering_text_payload_invalid_utf8() -> Self {
1164 Self::index_corruption()
1165 }
1166
1167 pub(crate) fn bytes_covering_text_payload_invalid_escape_byte() -> Self {
1169 Self::index_corruption()
1170 }
1171
1172 pub(crate) fn bytes_covering_text_payload_missing_terminator() -> Self {
1174 Self::index_corruption()
1175 }
1176
1177 #[must_use]
1179 pub fn missing_persisted_slot(field_name: &'static str) -> Self {
1180 Self::persisted_row_field_decode_corruption(field_name)
1181 }
1182
1183 pub(crate) fn identity_corruption() -> Self {
1185 Self::new(ErrorClass::Corruption, ErrorOrigin::Identity)
1186 }
1187
1188 #[cold]
1190 #[inline(never)]
1191 pub(crate) fn store_unsupported() -> Self {
1192 Self::new(ErrorClass::Unsupported, ErrorOrigin::Store)
1193 }
1194
1195 #[cfg(any(test, feature = "sql"))]
1197 pub(crate) fn schema_ddl_publication_race_lost(_entity_path: &'static str) -> Self {
1198 Self {
1199 class: ErrorClass::Unsupported,
1200 origin: ErrorOrigin::Store,
1201 detail: Some(ErrorDetail::Store(StoreError::SchemaDdlPublicationRaceLost)),
1202 }
1203 }
1204
1205 #[cfg(feature = "sql")]
1207 pub(crate) fn schema_ddl_rewrite_requires_migration(_entity_path: &'static str) -> Self {
1208 Self {
1209 class: ErrorClass::Unsupported,
1210 origin: ErrorOrigin::Store,
1211 detail: Some(ErrorDetail::Store(
1212 StoreError::SchemaDdlRewriteRequiresMigration,
1213 )),
1214 }
1215 }
1216
1217 pub(crate) fn schema_row_layout_version_exhausted() -> Self {
1219 Self {
1220 class: ErrorClass::Unsupported,
1221 origin: ErrorOrigin::Store,
1222 detail: Some(ErrorDetail::Store(
1223 StoreError::SchemaRowLayoutVersionExhausted,
1224 )),
1225 }
1226 }
1227
1228 pub(crate) fn schema_generated_field_after_ddl_field() -> Self {
1231 Self {
1232 class: ErrorClass::Unsupported,
1233 origin: ErrorOrigin::Store,
1234 detail: Some(ErrorDetail::Store(
1235 StoreError::SchemaGeneratedFieldAfterDdlField,
1236 )),
1237 }
1238 }
1239
1240 pub(crate) fn schema_transition_budget_exceeded(
1242 resource: SchemaTransitionBudgetResource,
1243 ) -> Self {
1244 Self {
1245 class: ErrorClass::Unsupported,
1246 origin: ErrorOrigin::Store,
1247 detail: Some(ErrorDetail::Store(
1248 StoreError::SchemaTransitionBudgetExceeded { resource },
1249 )),
1250 }
1251 }
1252
1253 #[cfg(feature = "sql")]
1255 pub(crate) fn schema_ddl_set_not_null_validation_failed(
1256 _entity_path: &'static str,
1257 _column_name: &str,
1258 ) -> Self {
1259 Self {
1260 class: ErrorClass::Unsupported,
1261 origin: ErrorOrigin::Store,
1262 detail: Some(ErrorDetail::Store(
1263 StoreError::SchemaDdlSetNotNullValidationFailed,
1264 )),
1265 }
1266 }
1267
1268 pub(crate) fn unsupported_entity_tag_in_data_store(
1270 _entity_tag: crate::types::EntityTag,
1271 ) -> Self {
1272 Self::store_unsupported()
1273 }
1274
1275 #[cfg(not(test))]
1277 pub(crate) fn commit_memory_id_registration_failed(_err: impl Sized) -> Self {
1278 Self::store_internal()
1279 }
1280
1281 pub(crate) fn index_unsupported() -> Self {
1283 Self::new(ErrorClass::Unsupported, ErrorOrigin::Index)
1284 }
1285
1286 pub(crate) fn index_component_exceeds_max_size() -> Self {
1288 Self::index_unsupported()
1289 }
1290
1291 pub(crate) fn serialize_unsupported() -> Self {
1293 Self::new(ErrorClass::Unsupported, ErrorOrigin::Serialize)
1294 }
1295
1296 pub(crate) fn cursor_invalid_continuation() -> Self {
1298 Self::new(ErrorClass::Unsupported, ErrorOrigin::Cursor)
1299 }
1300
1301 pub(crate) fn serialize_incompatible_persisted_format() -> Self {
1303 Self::new(
1304 ErrorClass::IncompatiblePersistedFormat,
1305 ErrorOrigin::Serialize,
1306 )
1307 }
1308
1309 #[cfg(feature = "sql")]
1312 pub(crate) fn query_unsupported_sql_feature(feature: diagnostic_code::SqlFeatureCode) -> Self {
1313 Self {
1314 class: ErrorClass::Unsupported,
1315 origin: ErrorOrigin::Query,
1316 detail: Some(ErrorDetail::Query(
1317 QueryErrorDetail::UnsupportedSqlFeature { feature },
1318 )),
1319 }
1320 }
1321
1322 #[cfg(feature = "sql")]
1325 pub(crate) fn query_sql_lowering(reason: diagnostic_code::SqlLoweringCode) -> Self {
1326 Self {
1327 class: ErrorClass::Unsupported,
1328 origin: ErrorOrigin::Query,
1329 detail: Some(ErrorDetail::Query(QueryErrorDetail::SqlLowering { reason })),
1330 }
1331 }
1332
1333 pub(crate) fn query_unsupported_projection(
1336 reason: diagnostic_code::QueryProjectionCode,
1337 ) -> Self {
1338 Self {
1339 class: ErrorClass::Unsupported,
1340 origin: ErrorOrigin::Query,
1341 detail: Some(ErrorDetail::Query(
1342 QueryErrorDetail::UnsupportedProjection { reason },
1343 )),
1344 }
1345 }
1346
1347 pub(crate) fn query_unknown_aggregate_target_field() -> Self {
1349 Self {
1350 class: ErrorClass::Unsupported,
1351 origin: ErrorOrigin::Query,
1352 detail: Some(ErrorDetail::Query(
1353 QueryErrorDetail::UnknownAggregateTargetField,
1354 )),
1355 }
1356 }
1357
1358 pub(crate) fn query_result_shape_mismatch(
1361 reason: diagnostic_code::QueryResultShapeCode,
1362 ) -> Self {
1363 Self {
1364 class: ErrorClass::Unsupported,
1365 origin: ErrorOrigin::Query,
1366 detail: Some(ErrorDetail::Query(QueryErrorDetail::ResultShapeMismatch {
1367 reason,
1368 })),
1369 }
1370 }
1371
1372 #[cfg(feature = "sql")]
1375 pub(crate) fn query_sql_surface_mismatch(
1376 mismatch: diagnostic_code::SqlSurfaceMismatchCode,
1377 ) -> Self {
1378 Self {
1379 class: ErrorClass::Unsupported,
1380 origin: ErrorOrigin::Query,
1381 detail: Some(ErrorDetail::Query(QueryErrorDetail::SqlSurfaceMismatch {
1382 mismatch,
1383 })),
1384 }
1385 }
1386
1387 pub(crate) fn query_sql_write_boundary(
1389 boundary: diagnostic_code::SqlWriteBoundaryCode,
1390 ) -> Self {
1391 Self {
1392 class: ErrorClass::Unsupported,
1393 origin: ErrorOrigin::Query,
1394 detail: Some(ErrorDetail::Query(QueryErrorDetail::SqlWriteBoundary {
1395 boundary,
1396 })),
1397 }
1398 }
1399
1400 pub fn store_not_found(_key: impl Sized) -> Self {
1401 Self {
1402 class: ErrorClass::NotFound,
1403 origin: ErrorOrigin::Store,
1404 detail: Some(ErrorDetail::Store(StoreError::NotFound)),
1405 }
1406 }
1407
1408 pub fn unsupported_entity_path(_path: impl Sized) -> Self {
1410 Self::store_unsupported()
1411 }
1412
1413 #[must_use]
1414 pub const fn is_not_found(&self) -> bool {
1415 matches!(self.detail, Some(ErrorDetail::Store(StoreError::NotFound)))
1416 }
1417
1418 #[cold]
1420 #[inline(never)]
1421 pub(crate) fn index_plan_corruption(origin: ErrorOrigin) -> Self {
1422 Self::new(ErrorClass::Corruption, origin)
1423 }
1424
1425 #[cold]
1427 #[inline(never)]
1428 pub(crate) fn index_plan_index_corruption() -> Self {
1429 Self::index_plan_corruption(ErrorOrigin::Index)
1430 }
1431
1432 #[cold]
1434 #[inline(never)]
1435 pub(crate) fn index_plan_store_corruption() -> Self {
1436 Self::index_plan_corruption(ErrorOrigin::Store)
1437 }
1438
1439 #[cold]
1441 #[inline(never)]
1442 pub(crate) fn index_plan_serialize_corruption() -> Self {
1443 Self::index_plan_corruption(ErrorOrigin::Serialize)
1444 }
1445
1446 #[cfg(test)]
1448 pub(crate) fn index_plan_invariant(origin: ErrorOrigin) -> Self {
1449 Self::new(ErrorClass::InvariantViolation, origin)
1450 }
1451
1452 #[cfg(test)]
1454 pub(crate) fn index_plan_store_invariant() -> Self {
1455 Self::index_plan_invariant(ErrorOrigin::Store)
1456 }
1457
1458 pub(crate) fn index_violation(_path: &str, _index_fields: &[&str]) -> Self {
1460 Self::new(ErrorClass::Conflict, ErrorOrigin::Index)
1461 }
1462}
1463
1464impl From<diagnostic_code::QueryReadAdmissionCode> for InternalError {
1465 fn from(reason: diagnostic_code::QueryReadAdmissionCode) -> Self {
1466 Self {
1467 class: ErrorClass::Unsupported,
1468 origin: ErrorOrigin::Query,
1469 detail: Some(ErrorDetail::Query(QueryErrorDetail::QueryReadAdmission {
1470 reason,
1471 })),
1472 }
1473 }
1474}
1475
1476impl fmt::Debug for InternalError {
1477 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1478 fmt_compact_diagnostic(
1479 f,
1480 self.diagnostic_code(),
1481 self.detail
1482 .as_ref()
1483 .and_then(ErrorDetail::diagnostic_detail),
1484 )
1485 }
1486}
1487
1488impl fmt::Display for InternalError {
1489 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1490 f.write_str(self.message())
1491 }
1492}
1493
1494impl std::error::Error for InternalError {}
1495
1496pub enum ErrorDetail {
1504 Executor(ExecutorErrorDetail),
1506 Store(StoreError),
1507 Query(QueryErrorDetail),
1508 Recovery(RecoveryErrorDetail),
1509 Serialize(SerializeErrorDetail),
1511 }
1514
1515pub enum ExecutorErrorDetail {
1517 MutationRequiredFieldMissing,
1519}
1520
1521pub enum SerializeErrorDetail {
1523 PersistedRowLayoutOutsideAcceptedWindow,
1525
1526 PersistedRowSlotCountMismatch,
1528}
1529
1530pub enum RecoveryErrorDetail {
1537 UnsupportedFormatVersion { found: Option<u16>, required: u16 },
1538
1539 MalformedFormatMarker { reason: RecoveryFormatMarkerError },
1540}
1541
1542#[derive(Clone, Copy, Eq, PartialEq)]
1544pub enum RecoveryFormatMarkerError {
1545 Magic,
1546 Checksum,
1547 State,
1548}
1549
1550pub enum StoreError {
1558 NotFound,
1559
1560 Corrupt,
1561
1562 InvariantViolation,
1563
1564 SchemaDdlPublicationRaceLost,
1565
1566 SchemaDdlRewriteRequiresMigration,
1567
1568 SchemaRowLayoutVersionExhausted,
1569
1570 SchemaTransitionBudgetExceeded {
1571 resource: SchemaTransitionBudgetResource,
1572 },
1573
1574 SchemaDdlSetNotNullValidationFailed,
1575
1576 SchemaGeneratedFieldAfterDdlField,
1578}
1579
1580pub enum QueryErrorDetail {
1587 NumericOverflow,
1588
1589 NumericNotRepresentable,
1590
1591 UnsupportedSqlFeature {
1592 feature: diagnostic_code::SqlFeatureCode,
1593 },
1594
1595 SqlLowering {
1596 reason: diagnostic_code::SqlLoweringCode,
1597 },
1598
1599 UnsupportedProjection {
1600 reason: diagnostic_code::QueryProjectionCode,
1601 },
1602
1603 UnknownAggregateTargetField,
1604
1605 ResultShapeMismatch {
1606 reason: diagnostic_code::QueryResultShapeCode,
1607 },
1608
1609 QueryReadAdmission {
1610 reason: diagnostic_code::QueryReadAdmissionCode,
1611 },
1612
1613 SqlSurfaceMismatch {
1614 mismatch: diagnostic_code::SqlSurfaceMismatchCode,
1615 },
1616
1617 SqlWriteBoundary {
1618 boundary: diagnostic_code::SqlWriteBoundaryCode,
1619 },
1620
1621 SchemaDdlAdmission {
1622 error: SchemaDdlAdmissionError,
1623 },
1624
1625 StaleSchemaRevision,
1626}
1627
1628impl fmt::Display for QueryErrorDetail {
1629 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1630 f.write_str(COMPACT_QUERY_DIAGNOSTIC_MESSAGE)
1631 }
1632}
1633
1634impl std::error::Error for QueryErrorDetail {}
1635
1636#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1644pub enum SchemaTransitionBudgetResource {
1645 DeletionKeys,
1647 ProjectionEntries,
1649 ProjectionWorkUnits,
1651 SourceRows,
1653 SourceRowBytes,
1655 StagedRawBytes,
1657}
1658
1659#[derive(Clone, Copy, Eq, PartialEq)]
1668pub enum SchemaDdlAdmissionError {
1669 MissingExpectedSchemaVersion,
1670
1671 MissingNextSchemaVersion,
1672
1673 StaleExpectedSchemaVersion,
1674
1675 InvalidExpectedSchemaVersion,
1676
1677 InvalidNextSchemaVersion,
1678
1679 AcceptedSchemaChangeWithoutVersionBump,
1680
1681 EmptyVersionBump,
1682
1683 VersionGap,
1684
1685 VersionRollback,
1686
1687 FingerprintMethodMismatch,
1688
1689 UnsupportedTransitionClass,
1690
1691 PhysicalRunnerMissing,
1692
1693 ValidationFailed,
1694
1695 PublicationRaceLost,
1696
1697 InvalidAddColumnDefault,
1698
1699 InvalidAlterColumnDefault,
1700
1701 RowLayoutVersionExhausted,
1702
1703 GeneratedIndexDropRejected,
1704
1705 SchemaRewriteRequiresMigration,
1706
1707 SchemaTransitionBudgetExceeded {
1708 resource: SchemaTransitionBudgetResource,
1709 },
1710
1711 GeneratedFieldDefaultChangeRejected,
1712
1713 GeneratedFieldNullabilityChangeRejected,
1714
1715 SetNotNullValidationFailed,
1716}
1717
1718impl fmt::Display for SchemaDdlAdmissionError {
1719 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1720 f.write_str(COMPACT_QUERY_DIAGNOSTIC_MESSAGE)
1721 }
1722}
1723
1724impl std::error::Error for SchemaDdlAdmissionError {}
1725
1726impl fmt::Debug for ErrorDetail {
1727 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1728 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
1729 }
1730}
1731
1732impl fmt::Debug for ExecutorErrorDetail {
1733 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1734 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
1735 }
1736}
1737
1738impl fmt::Debug for StoreError {
1739 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1740 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
1741 }
1742}
1743
1744impl fmt::Debug for QueryErrorDetail {
1745 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1746 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
1747 }
1748}
1749
1750impl fmt::Debug for RecoveryErrorDetail {
1751 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1752 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
1753 }
1754}
1755
1756impl fmt::Debug for SerializeErrorDetail {
1757 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1758 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
1759 }
1760}
1761
1762impl fmt::Debug for RecoveryFormatMarkerError {
1763 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1764 fmt_compact_diagnostic(
1765 f,
1766 diagnostic_code::DiagnosticCode::RuntimeCorruption,
1767 Some(diagnostic_code::DiagnosticDetail::RuntimeKind {
1768 kind: diagnostic_code::RuntimeErrorKind::Corruption,
1769 }),
1770 )
1771 }
1772}
1773
1774impl fmt::Debug for SchemaDdlAdmissionError {
1775 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1776 fmt_compact_diagnostic(
1777 f,
1778 diagnostic_code::DiagnosticCode::SchemaDdlAdmission,
1779 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
1780 reason: self.diagnostic_code(),
1781 }),
1782 )
1783 }
1784}
1785
1786fn fmt_compact_diagnostic(
1787 f: &mut fmt::Formatter<'_>,
1788 code: diagnostic_code::DiagnosticCode,
1789 detail: Option<diagnostic_code::DiagnosticDetail>,
1790) -> fmt::Result {
1791 write!(
1792 f,
1793 "{}",
1794 diagnostic_code::ErrorCode::from_parts(code, detail).raw()
1795 )
1796}
1797
1798impl ErrorDetail {
1799 #[must_use]
1801 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
1802 match self {
1803 Self::Executor(error) => error.diagnostic_code(),
1804 Self::Store(error) => error.diagnostic_code(),
1805 Self::Query(error) => error.diagnostic_code(),
1806 Self::Recovery(error) => error.diagnostic_code(),
1807 Self::Serialize(error) => error.diagnostic_code(),
1808 }
1809 }
1810
1811 #[must_use]
1813 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
1814 match self {
1815 Self::Executor(error) => error.diagnostic_detail(),
1816 Self::Store(error) => error.diagnostic_detail(),
1817 Self::Query(error) => error.diagnostic_detail(),
1818 Self::Recovery(error) => error.diagnostic_detail(),
1819 Self::Serialize(error) => error.diagnostic_detail(),
1820 }
1821 }
1822}
1823
1824impl ExecutorErrorDetail {
1825 #[must_use]
1827 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
1828 match self {
1829 Self::MutationRequiredFieldMissing => {
1830 diagnostic_code::DiagnosticCode::RuntimeUnsupported
1831 }
1832 }
1833 }
1834
1835 #[must_use]
1837 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
1838 match self {
1839 Self::MutationRequiredFieldMissing => {
1840 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
1841 boundary: diagnostic_code::RuntimeBoundaryCode::MutationRequiredFieldMissing,
1842 })
1843 }
1844 }
1845 }
1846}
1847
1848impl RecoveryErrorDetail {
1849 #[must_use]
1851 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
1852 match self {
1853 Self::UnsupportedFormatVersion { .. } => {
1854 diagnostic_code::DiagnosticCode::RuntimeIncompatiblePersistedFormat
1855 }
1856 Self::MalformedFormatMarker { .. } => {
1857 diagnostic_code::DiagnosticCode::RuntimeCorruption
1858 }
1859 }
1860 }
1861
1862 #[must_use]
1864 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
1865 let kind = match self {
1866 Self::UnsupportedFormatVersion { .. } => {
1867 diagnostic_code::RuntimeErrorKind::IncompatiblePersistedFormat
1868 }
1869 Self::MalformedFormatMarker { .. } => diagnostic_code::RuntimeErrorKind::Corruption,
1870 };
1871
1872 Some(diagnostic_code::DiagnosticDetail::RuntimeKind { kind })
1873 }
1874}
1875
1876impl SerializeErrorDetail {
1877 #[must_use]
1879 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
1880 match self {
1881 Self::PersistedRowLayoutOutsideAcceptedWindow | Self::PersistedRowSlotCountMismatch => {
1882 diagnostic_code::DiagnosticCode::RuntimeCorruption
1883 }
1884 }
1885 }
1886
1887 #[must_use]
1889 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
1890 let boundary = match self {
1891 Self::PersistedRowLayoutOutsideAcceptedWindow => {
1892 diagnostic_code::RuntimeBoundaryCode::PersistedRowLayoutOutsideAcceptedWindow
1893 }
1894 Self::PersistedRowSlotCountMismatch => {
1895 diagnostic_code::RuntimeBoundaryCode::PersistedRowSlotCountMismatch
1896 }
1897 };
1898
1899 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary { boundary })
1900 }
1901}
1902
1903impl StoreError {
1904 #[must_use]
1906 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
1907 match self {
1908 Self::NotFound => diagnostic_code::DiagnosticCode::StoreNotFound,
1909 Self::Corrupt => diagnostic_code::DiagnosticCode::StoreCorruption,
1910 Self::InvariantViolation => diagnostic_code::DiagnosticCode::StoreInvariantViolation,
1911 Self::SchemaDdlPublicationRaceLost
1912 | Self::SchemaDdlRewriteRequiresMigration
1913 | Self::SchemaRowLayoutVersionExhausted
1914 | Self::SchemaTransitionBudgetExceeded { .. }
1915 | Self::SchemaDdlSetNotNullValidationFailed => {
1916 diagnostic_code::DiagnosticCode::SchemaDdlAdmission
1917 }
1918 Self::SchemaGeneratedFieldAfterDdlField => {
1919 diagnostic_code::DiagnosticCode::RuntimeUnsupported
1920 }
1921 }
1922 }
1923
1924 #[must_use]
1926 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
1927 match self {
1928 Self::SchemaDdlPublicationRaceLost => {
1929 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
1930 reason: diagnostic_code::SchemaDdlAdmissionCode::PublicationRaceLost,
1931 })
1932 }
1933 Self::SchemaDdlRewriteRequiresMigration => {
1934 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
1935 reason: diagnostic_code::SchemaDdlAdmissionCode::SchemaRewriteRequiresMigration,
1936 })
1937 }
1938 Self::SchemaRowLayoutVersionExhausted => {
1939 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
1940 reason: diagnostic_code::SchemaDdlAdmissionCode::RowLayoutVersionExhausted,
1941 })
1942 }
1943 Self::SchemaTransitionBudgetExceeded { .. } => {
1944 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
1945 reason: diagnostic_code::SchemaDdlAdmissionCode::SchemaTransitionBudgetExceeded,
1946 })
1947 }
1948 Self::SchemaDdlSetNotNullValidationFailed => {
1949 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
1950 reason: diagnostic_code::SchemaDdlAdmissionCode::SetNotNullValidationFailed,
1951 })
1952 }
1953 Self::SchemaGeneratedFieldAfterDdlField => {
1954 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
1955 boundary: diagnostic_code::RuntimeBoundaryCode::GeneratedFieldAfterDdlField,
1956 })
1957 }
1958 Self::NotFound | Self::Corrupt | Self::InvariantViolation => None,
1959 }
1960 }
1961}
1962
1963impl QueryErrorDetail {
1964 #[must_use]
1966 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
1967 match self {
1968 Self::NumericOverflow => diagnostic_code::DiagnosticCode::QueryNumericOverflow,
1969 Self::NumericNotRepresentable => {
1970 diagnostic_code::DiagnosticCode::QueryNumericNotRepresentable
1971 }
1972 Self::UnsupportedSqlFeature { .. } => {
1973 diagnostic_code::DiagnosticCode::QueryUnsupportedSqlFeature
1974 }
1975 Self::SqlLowering { .. } => diagnostic_code::DiagnosticCode::QueryUnsupportedSqlFeature,
1976 Self::UnsupportedProjection { .. } => {
1977 diagnostic_code::DiagnosticCode::QueryUnsupportedProjection
1978 }
1979 Self::UnknownAggregateTargetField => {
1980 diagnostic_code::DiagnosticCode::QueryUnknownAggregateTargetField
1981 }
1982 Self::ResultShapeMismatch { .. } => {
1983 diagnostic_code::DiagnosticCode::QueryResultShapeMismatch
1984 }
1985 Self::QueryReadAdmission { .. } => diagnostic_code::DiagnosticCode::QueryReadAdmission,
1986 Self::SqlSurfaceMismatch { .. } => {
1987 diagnostic_code::DiagnosticCode::QuerySqlSurfaceMismatch
1988 }
1989 Self::SqlWriteBoundary { .. } => diagnostic_code::DiagnosticCode::QuerySqlWriteBoundary,
1990 Self::SchemaDdlAdmission { .. } => diagnostic_code::DiagnosticCode::SchemaDdlAdmission,
1991 Self::StaleSchemaRevision => diagnostic_code::DiagnosticCode::RuntimeConflict,
1992 }
1993 }
1994
1995 #[must_use]
1997 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
1998 match self {
1999 Self::UnsupportedSqlFeature { feature } => {
2000 Some(diagnostic_code::DiagnosticDetail::UnsupportedSqlFeature { feature: *feature })
2001 }
2002 Self::SqlLowering { reason } => {
2003 Some(diagnostic_code::DiagnosticDetail::SqlLowering { reason: *reason })
2004 }
2005 Self::UnsupportedProjection { reason } => {
2006 Some(diagnostic_code::DiagnosticDetail::QueryProjection { reason: *reason })
2007 }
2008 Self::ResultShapeMismatch { reason } => {
2009 Some(diagnostic_code::DiagnosticDetail::QueryResultShape { reason: *reason })
2010 }
2011 Self::QueryReadAdmission { reason } => {
2012 Some(diagnostic_code::DiagnosticDetail::QueryReadAdmission { reason: *reason })
2013 }
2014 Self::SqlSurfaceMismatch { mismatch } => {
2015 Some(diagnostic_code::DiagnosticDetail::SqlSurfaceMismatch {
2016 mismatch: *mismatch,
2017 })
2018 }
2019 Self::SqlWriteBoundary { boundary } => {
2020 Some(diagnostic_code::DiagnosticDetail::SqlWriteBoundary {
2021 boundary: *boundary,
2022 })
2023 }
2024 Self::SchemaDdlAdmission { error } => {
2025 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2026 reason: error.diagnostic_code(),
2027 })
2028 }
2029 Self::NumericOverflow
2030 | Self::NumericNotRepresentable
2031 | Self::UnknownAggregateTargetField
2032 | Self::StaleSchemaRevision => None,
2033 }
2034 }
2035}
2036
2037impl SchemaDdlAdmissionError {
2038 #[must_use]
2040 pub const fn diagnostic_code(&self) -> diagnostic_code::SchemaDdlAdmissionCode {
2041 match self {
2042 Self::MissingExpectedSchemaVersion => {
2043 diagnostic_code::SchemaDdlAdmissionCode::MissingExpectedSchemaVersion
2044 }
2045 Self::MissingNextSchemaVersion => {
2046 diagnostic_code::SchemaDdlAdmissionCode::MissingNextSchemaVersion
2047 }
2048 Self::StaleExpectedSchemaVersion => {
2049 diagnostic_code::SchemaDdlAdmissionCode::StaleExpectedSchemaVersion
2050 }
2051 Self::InvalidExpectedSchemaVersion => {
2052 diagnostic_code::SchemaDdlAdmissionCode::InvalidExpectedSchemaVersion
2053 }
2054 Self::InvalidNextSchemaVersion => {
2055 diagnostic_code::SchemaDdlAdmissionCode::InvalidNextSchemaVersion
2056 }
2057 Self::AcceptedSchemaChangeWithoutVersionBump => {
2058 diagnostic_code::SchemaDdlAdmissionCode::AcceptedSchemaChangeWithoutVersionBump
2059 }
2060 Self::EmptyVersionBump => diagnostic_code::SchemaDdlAdmissionCode::EmptyVersionBump,
2061 Self::VersionGap => diagnostic_code::SchemaDdlAdmissionCode::VersionGap,
2062 Self::VersionRollback => diagnostic_code::SchemaDdlAdmissionCode::VersionRollback,
2063 Self::FingerprintMethodMismatch => {
2064 diagnostic_code::SchemaDdlAdmissionCode::FingerprintMethodMismatch
2065 }
2066 Self::UnsupportedTransitionClass => {
2067 diagnostic_code::SchemaDdlAdmissionCode::UnsupportedTransitionClass
2068 }
2069 Self::PhysicalRunnerMissing => {
2070 diagnostic_code::SchemaDdlAdmissionCode::PhysicalRunnerMissing
2071 }
2072 Self::ValidationFailed => diagnostic_code::SchemaDdlAdmissionCode::ValidationFailed,
2073 Self::PublicationRaceLost => {
2074 diagnostic_code::SchemaDdlAdmissionCode::PublicationRaceLost
2075 }
2076 Self::InvalidAddColumnDefault => {
2077 diagnostic_code::SchemaDdlAdmissionCode::InvalidAddColumnDefault
2078 }
2079 Self::InvalidAlterColumnDefault => {
2080 diagnostic_code::SchemaDdlAdmissionCode::InvalidAlterColumnDefault
2081 }
2082 Self::GeneratedIndexDropRejected => {
2083 diagnostic_code::SchemaDdlAdmissionCode::GeneratedIndexDropRejected
2084 }
2085 Self::SchemaRewriteRequiresMigration => {
2086 diagnostic_code::SchemaDdlAdmissionCode::SchemaRewriteRequiresMigration
2087 }
2088 Self::SchemaTransitionBudgetExceeded { .. } => {
2089 diagnostic_code::SchemaDdlAdmissionCode::SchemaTransitionBudgetExceeded
2090 }
2091 Self::GeneratedFieldDefaultChangeRejected => {
2092 diagnostic_code::SchemaDdlAdmissionCode::GeneratedFieldDefaultChangeRejected
2093 }
2094 Self::GeneratedFieldNullabilityChangeRejected => {
2095 diagnostic_code::SchemaDdlAdmissionCode::GeneratedFieldNullabilityChangeRejected
2096 }
2097 Self::SetNotNullValidationFailed => {
2098 diagnostic_code::SchemaDdlAdmissionCode::SetNotNullValidationFailed
2099 }
2100 Self::RowLayoutVersionExhausted => {
2101 diagnostic_code::SchemaDdlAdmissionCode::RowLayoutVersionExhausted
2102 }
2103 }
2104 }
2105}
2106
2107#[repr(u8)]
2114#[derive(Clone, Copy, Eq, PartialEq)]
2115pub enum ErrorClass {
2116 Corruption,
2117 IncompatiblePersistedFormat,
2118 NotFound,
2119 Internal,
2120 Conflict,
2121 Unsupported,
2122 InvariantViolation,
2123}
2124
2125impl ErrorClass {
2126 #[must_use]
2128 pub const fn diagnostic_code(self, origin: ErrorOrigin) -> diagnostic_code::DiagnosticCode {
2129 match self {
2130 Self::Corruption if matches!(origin, ErrorOrigin::Store) => {
2131 diagnostic_code::DiagnosticCode::StoreCorruption
2132 }
2133 Self::Corruption => diagnostic_code::DiagnosticCode::RuntimeCorruption,
2134 Self::IncompatiblePersistedFormat => {
2135 diagnostic_code::DiagnosticCode::RuntimeIncompatiblePersistedFormat
2136 }
2137 Self::NotFound if matches!(origin, ErrorOrigin::Store) => {
2138 diagnostic_code::DiagnosticCode::StoreNotFound
2139 }
2140 Self::NotFound => diagnostic_code::DiagnosticCode::RuntimeNotFound,
2141 Self::Internal => diagnostic_code::DiagnosticCode::RuntimeInternal,
2142 Self::Conflict => diagnostic_code::DiagnosticCode::RuntimeConflict,
2143 Self::Unsupported if matches!(origin, ErrorOrigin::Cursor) => {
2144 diagnostic_code::DiagnosticCode::QueryInvalidContinuationCursor
2145 }
2146 Self::Unsupported => diagnostic_code::DiagnosticCode::RuntimeUnsupported,
2147 Self::InvariantViolation if matches!(origin, ErrorOrigin::Store) => {
2148 diagnostic_code::DiagnosticCode::StoreInvariantViolation
2149 }
2150 Self::InvariantViolation => diagnostic_code::DiagnosticCode::RuntimeInvariantViolation,
2151 }
2152 }
2153}
2154
2155impl fmt::Debug for ErrorClass {
2156 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2157 write!(f, "{}", *self as u8)
2158 }
2159}
2160
2161#[repr(u8)]
2168#[derive(Clone, Copy, Eq, PartialEq)]
2169pub enum ErrorOrigin {
2170 Serialize,
2171 Store,
2172 Index,
2173 Identity,
2174 Query,
2175 Planner,
2176 Cursor,
2177 Recovery,
2178 Response,
2179 Executor,
2180 Interface,
2181}
2182
2183impl ErrorOrigin {
2184 #[must_use]
2186 pub const fn diagnostic_origin(self) -> diagnostic_code::ErrorOrigin {
2187 match self {
2188 Self::Serialize => diagnostic_code::ErrorOrigin::Serialize,
2189 Self::Store => diagnostic_code::ErrorOrigin::Store,
2190 Self::Index => diagnostic_code::ErrorOrigin::Index,
2191 Self::Identity => diagnostic_code::ErrorOrigin::Identity,
2192 Self::Query => diagnostic_code::ErrorOrigin::Query,
2193 Self::Planner => diagnostic_code::ErrorOrigin::Planner,
2194 Self::Cursor => diagnostic_code::ErrorOrigin::Cursor,
2195 Self::Recovery => diagnostic_code::ErrorOrigin::Recovery,
2196 Self::Response => diagnostic_code::ErrorOrigin::Response,
2197 Self::Executor => diagnostic_code::ErrorOrigin::Executor,
2198 Self::Interface => diagnostic_code::ErrorOrigin::Interface,
2199 }
2200 }
2201}
2202
2203impl fmt::Debug for ErrorOrigin {
2204 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2205 write!(f, "{}", *self as u8)
2206 }
2207}