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 journal_mutation_revision_exhausted() -> Self {
1230 Self {
1231 class: ErrorClass::Unsupported,
1232 origin: ErrorOrigin::Store,
1233 detail: Some(ErrorDetail::Store(
1234 StoreError::JournalMutationRevisionExhausted,
1235 )),
1236 }
1237 }
1238
1239 pub(crate) fn schema_generated_field_after_ddl_field() -> Self {
1242 Self {
1243 class: ErrorClass::Unsupported,
1244 origin: ErrorOrigin::Store,
1245 detail: Some(ErrorDetail::Store(
1246 StoreError::SchemaGeneratedFieldAfterDdlField,
1247 )),
1248 }
1249 }
1250
1251 pub(crate) fn schema_transition_budget_exceeded(
1253 resource: SchemaTransitionBudgetResource,
1254 ) -> Self {
1255 Self {
1256 class: ErrorClass::Unsupported,
1257 origin: ErrorOrigin::Store,
1258 detail: Some(ErrorDetail::Store(
1259 StoreError::SchemaTransitionBudgetExceeded { resource },
1260 )),
1261 }
1262 }
1263
1264 #[cfg(feature = "sql")]
1266 pub(crate) fn schema_ddl_set_not_null_validation_failed(
1267 _entity_path: &'static str,
1268 _column_name: &str,
1269 ) -> Self {
1270 Self {
1271 class: ErrorClass::Unsupported,
1272 origin: ErrorOrigin::Store,
1273 detail: Some(ErrorDetail::Store(
1274 StoreError::SchemaDdlSetNotNullValidationFailed,
1275 )),
1276 }
1277 }
1278
1279 pub(crate) fn unsupported_entity_tag_in_data_store(
1281 _entity_tag: crate::types::EntityTag,
1282 ) -> Self {
1283 Self::store_unsupported()
1284 }
1285
1286 #[cfg(not(test))]
1288 pub(crate) fn commit_memory_id_registration_failed(_err: impl Sized) -> Self {
1289 Self::store_internal()
1290 }
1291
1292 pub(crate) fn index_unsupported() -> Self {
1294 Self::new(ErrorClass::Unsupported, ErrorOrigin::Index)
1295 }
1296
1297 pub(crate) fn index_component_exceeds_max_size() -> Self {
1299 Self::index_unsupported()
1300 }
1301
1302 pub(crate) fn serialize_unsupported() -> Self {
1304 Self::new(ErrorClass::Unsupported, ErrorOrigin::Serialize)
1305 }
1306
1307 pub(crate) fn cursor_invalid_continuation() -> Self {
1309 Self::new(ErrorClass::Unsupported, ErrorOrigin::Cursor)
1310 }
1311
1312 pub(crate) fn serialize_incompatible_persisted_format() -> Self {
1314 Self::new(
1315 ErrorClass::IncompatiblePersistedFormat,
1316 ErrorOrigin::Serialize,
1317 )
1318 }
1319
1320 #[cfg(feature = "sql")]
1323 pub(crate) fn query_unsupported_sql_feature(feature: diagnostic_code::SqlFeatureCode) -> Self {
1324 Self {
1325 class: ErrorClass::Unsupported,
1326 origin: ErrorOrigin::Query,
1327 detail: Some(ErrorDetail::Query(
1328 QueryErrorDetail::UnsupportedSqlFeature { feature },
1329 )),
1330 }
1331 }
1332
1333 #[cfg(feature = "sql")]
1336 pub(crate) fn query_sql_lowering(reason: diagnostic_code::SqlLoweringCode) -> Self {
1337 Self {
1338 class: ErrorClass::Unsupported,
1339 origin: ErrorOrigin::Query,
1340 detail: Some(ErrorDetail::Query(QueryErrorDetail::SqlLowering { reason })),
1341 }
1342 }
1343
1344 pub(crate) fn query_unsupported_projection(
1347 reason: diagnostic_code::QueryProjectionCode,
1348 ) -> Self {
1349 Self {
1350 class: ErrorClass::Unsupported,
1351 origin: ErrorOrigin::Query,
1352 detail: Some(ErrorDetail::Query(
1353 QueryErrorDetail::UnsupportedProjection { reason },
1354 )),
1355 }
1356 }
1357
1358 pub(crate) fn query_unknown_aggregate_target_field() -> Self {
1360 Self {
1361 class: ErrorClass::Unsupported,
1362 origin: ErrorOrigin::Query,
1363 detail: Some(ErrorDetail::Query(
1364 QueryErrorDetail::UnknownAggregateTargetField,
1365 )),
1366 }
1367 }
1368
1369 pub(crate) fn query_result_shape_mismatch(
1372 reason: diagnostic_code::QueryResultShapeCode,
1373 ) -> Self {
1374 Self {
1375 class: ErrorClass::Unsupported,
1376 origin: ErrorOrigin::Query,
1377 detail: Some(ErrorDetail::Query(QueryErrorDetail::ResultShapeMismatch {
1378 reason,
1379 })),
1380 }
1381 }
1382
1383 #[cfg(feature = "sql")]
1386 pub(crate) fn query_sql_surface_mismatch(
1387 mismatch: diagnostic_code::SqlSurfaceMismatchCode,
1388 ) -> Self {
1389 Self {
1390 class: ErrorClass::Unsupported,
1391 origin: ErrorOrigin::Query,
1392 detail: Some(ErrorDetail::Query(QueryErrorDetail::SqlSurfaceMismatch {
1393 mismatch,
1394 })),
1395 }
1396 }
1397
1398 pub(crate) fn query_sql_write_boundary(
1400 boundary: diagnostic_code::SqlWriteBoundaryCode,
1401 ) -> Self {
1402 Self {
1403 class: ErrorClass::Unsupported,
1404 origin: ErrorOrigin::Query,
1405 detail: Some(ErrorDetail::Query(QueryErrorDetail::SqlWriteBoundary {
1406 boundary,
1407 })),
1408 }
1409 }
1410
1411 pub fn store_not_found(_key: impl Sized) -> Self {
1412 Self {
1413 class: ErrorClass::NotFound,
1414 origin: ErrorOrigin::Store,
1415 detail: Some(ErrorDetail::Store(StoreError::NotFound)),
1416 }
1417 }
1418
1419 pub fn unsupported_entity_path(_path: impl Sized) -> Self {
1421 Self::store_unsupported()
1422 }
1423
1424 #[must_use]
1425 pub const fn is_not_found(&self) -> bool {
1426 matches!(self.detail, Some(ErrorDetail::Store(StoreError::NotFound)))
1427 }
1428
1429 #[cold]
1431 #[inline(never)]
1432 pub(crate) fn index_plan_corruption(origin: ErrorOrigin) -> Self {
1433 Self::new(ErrorClass::Corruption, origin)
1434 }
1435
1436 #[cold]
1438 #[inline(never)]
1439 pub(crate) fn index_plan_index_corruption() -> Self {
1440 Self::index_plan_corruption(ErrorOrigin::Index)
1441 }
1442
1443 #[cold]
1445 #[inline(never)]
1446 pub(crate) fn index_plan_store_corruption() -> Self {
1447 Self::index_plan_corruption(ErrorOrigin::Store)
1448 }
1449
1450 #[cold]
1452 #[inline(never)]
1453 pub(crate) fn index_plan_serialize_corruption() -> Self {
1454 Self::index_plan_corruption(ErrorOrigin::Serialize)
1455 }
1456
1457 #[cfg(test)]
1459 pub(crate) fn index_plan_invariant(origin: ErrorOrigin) -> Self {
1460 Self::new(ErrorClass::InvariantViolation, origin)
1461 }
1462
1463 #[cfg(test)]
1465 pub(crate) fn index_plan_store_invariant() -> Self {
1466 Self::index_plan_invariant(ErrorOrigin::Store)
1467 }
1468
1469 pub(crate) fn index_violation(_path: &str, _index_fields: &[&str]) -> Self {
1471 Self::new(ErrorClass::Conflict, ErrorOrigin::Index)
1472 }
1473}
1474
1475impl From<diagnostic_code::QueryReadAdmissionCode> for InternalError {
1476 fn from(reason: diagnostic_code::QueryReadAdmissionCode) -> Self {
1477 Self {
1478 class: ErrorClass::Unsupported,
1479 origin: ErrorOrigin::Query,
1480 detail: Some(ErrorDetail::Query(QueryErrorDetail::QueryReadAdmission {
1481 reason,
1482 })),
1483 }
1484 }
1485}
1486
1487impl fmt::Debug for InternalError {
1488 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1489 fmt_compact_diagnostic(
1490 f,
1491 self.diagnostic_code(),
1492 self.detail
1493 .as_ref()
1494 .and_then(ErrorDetail::diagnostic_detail),
1495 )
1496 }
1497}
1498
1499impl fmt::Display for InternalError {
1500 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1501 f.write_str(self.message())
1502 }
1503}
1504
1505impl std::error::Error for InternalError {}
1506
1507pub enum ErrorDetail {
1515 Executor(ExecutorErrorDetail),
1517 Store(StoreError),
1518 Query(QueryErrorDetail),
1519 Recovery(RecoveryErrorDetail),
1520 Serialize(SerializeErrorDetail),
1522 }
1525
1526pub enum ExecutorErrorDetail {
1528 MutationRequiredFieldMissing,
1530}
1531
1532pub enum SerializeErrorDetail {
1534 PersistedRowLayoutOutsideAcceptedWindow,
1536
1537 PersistedRowSlotCountMismatch,
1539}
1540
1541pub enum RecoveryErrorDetail {
1548 UnsupportedFormatVersion { found: Option<u16>, required: u16 },
1549
1550 MalformedFormatMarker { reason: RecoveryFormatMarkerError },
1551}
1552
1553#[derive(Clone, Copy, Eq, PartialEq)]
1555pub enum RecoveryFormatMarkerError {
1556 Magic,
1557 Checksum,
1558 State,
1559}
1560
1561pub enum StoreError {
1569 NotFound,
1570
1571 Corrupt,
1572
1573 InvariantViolation,
1574
1575 SchemaDdlPublicationRaceLost,
1576
1577 SchemaDdlRewriteRequiresMigration,
1578
1579 SchemaRowLayoutVersionExhausted,
1580
1581 JournalMutationRevisionExhausted,
1582
1583 SchemaTransitionBudgetExceeded {
1584 resource: SchemaTransitionBudgetResource,
1585 },
1586
1587 SchemaDdlSetNotNullValidationFailed,
1588
1589 SchemaGeneratedFieldAfterDdlField,
1591}
1592
1593pub enum QueryErrorDetail {
1600 NumericOverflow,
1601
1602 NumericNotRepresentable,
1603
1604 UnsupportedSqlFeature {
1605 feature: diagnostic_code::SqlFeatureCode,
1606 },
1607
1608 SqlLowering {
1609 reason: diagnostic_code::SqlLoweringCode,
1610 },
1611
1612 UnsupportedProjection {
1613 reason: diagnostic_code::QueryProjectionCode,
1614 },
1615
1616 UnknownAggregateTargetField,
1617
1618 ResultShapeMismatch {
1619 reason: diagnostic_code::QueryResultShapeCode,
1620 },
1621
1622 QueryReadAdmission {
1623 reason: diagnostic_code::QueryReadAdmissionCode,
1624 },
1625
1626 SqlSurfaceMismatch {
1627 mismatch: diagnostic_code::SqlSurfaceMismatchCode,
1628 },
1629
1630 SqlWriteBoundary {
1631 boundary: diagnostic_code::SqlWriteBoundaryCode,
1632 },
1633
1634 SchemaDdlAdmission {
1635 error: SchemaDdlAdmissionError,
1636 },
1637
1638 StaleSchemaRevision,
1639}
1640
1641impl fmt::Display for QueryErrorDetail {
1642 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1643 f.write_str(COMPACT_QUERY_DIAGNOSTIC_MESSAGE)
1644 }
1645}
1646
1647impl std::error::Error for QueryErrorDetail {}
1648
1649#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1657pub enum SchemaTransitionBudgetResource {
1658 DeletionKeys,
1660 ProjectionEntries,
1662 ProjectionWorkUnits,
1664 SourceRows,
1666 SourceRowBytes,
1668 StagedRawBytes,
1670}
1671
1672#[derive(Clone, Copy, Eq, PartialEq)]
1681pub enum SchemaDdlAdmissionError {
1682 MissingExpectedSchemaVersion,
1683
1684 MissingNextSchemaVersion,
1685
1686 StaleExpectedSchemaVersion,
1687
1688 InvalidExpectedSchemaVersion,
1689
1690 InvalidNextSchemaVersion,
1691
1692 AcceptedSchemaChangeWithoutVersionBump,
1693
1694 EmptyVersionBump,
1695
1696 VersionGap,
1697
1698 VersionRollback,
1699
1700 FingerprintMethodMismatch,
1701
1702 UnsupportedTransitionClass,
1703
1704 PhysicalRunnerMissing,
1705
1706 ValidationFailed,
1707
1708 PublicationRaceLost,
1709
1710 InvalidAddColumnDefault,
1711
1712 InvalidAlterColumnDefault,
1713
1714 RowLayoutVersionExhausted,
1715
1716 GeneratedIndexDropRejected,
1717
1718 SchemaRewriteRequiresMigration,
1719
1720 SchemaTransitionBudgetExceeded {
1721 resource: SchemaTransitionBudgetResource,
1722 },
1723
1724 GeneratedFieldDefaultChangeRejected,
1725
1726 GeneratedFieldNullabilityChangeRejected,
1727
1728 SetNotNullValidationFailed,
1729}
1730
1731impl fmt::Display for SchemaDdlAdmissionError {
1732 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1733 f.write_str(COMPACT_QUERY_DIAGNOSTIC_MESSAGE)
1734 }
1735}
1736
1737impl std::error::Error for SchemaDdlAdmissionError {}
1738
1739impl fmt::Debug for ErrorDetail {
1740 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1741 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
1742 }
1743}
1744
1745impl fmt::Debug for ExecutorErrorDetail {
1746 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1747 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
1748 }
1749}
1750
1751impl fmt::Debug for StoreError {
1752 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1753 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
1754 }
1755}
1756
1757impl fmt::Debug for QueryErrorDetail {
1758 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1759 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
1760 }
1761}
1762
1763impl fmt::Debug for RecoveryErrorDetail {
1764 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1765 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
1766 }
1767}
1768
1769impl fmt::Debug for SerializeErrorDetail {
1770 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1771 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
1772 }
1773}
1774
1775impl fmt::Debug for RecoveryFormatMarkerError {
1776 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1777 fmt_compact_diagnostic(
1778 f,
1779 diagnostic_code::DiagnosticCode::RuntimeCorruption,
1780 Some(diagnostic_code::DiagnosticDetail::RuntimeKind {
1781 kind: diagnostic_code::RuntimeErrorKind::Corruption,
1782 }),
1783 )
1784 }
1785}
1786
1787impl fmt::Debug for SchemaDdlAdmissionError {
1788 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1789 fmt_compact_diagnostic(
1790 f,
1791 diagnostic_code::DiagnosticCode::SchemaDdlAdmission,
1792 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
1793 reason: self.diagnostic_code(),
1794 }),
1795 )
1796 }
1797}
1798
1799fn fmt_compact_diagnostic(
1800 f: &mut fmt::Formatter<'_>,
1801 code: diagnostic_code::DiagnosticCode,
1802 detail: Option<diagnostic_code::DiagnosticDetail>,
1803) -> fmt::Result {
1804 write!(
1805 f,
1806 "{}",
1807 diagnostic_code::ErrorCode::from_parts(code, detail).raw()
1808 )
1809}
1810
1811impl ErrorDetail {
1812 #[must_use]
1814 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
1815 match self {
1816 Self::Executor(error) => error.diagnostic_code(),
1817 Self::Store(error) => error.diagnostic_code(),
1818 Self::Query(error) => error.diagnostic_code(),
1819 Self::Recovery(error) => error.diagnostic_code(),
1820 Self::Serialize(error) => error.diagnostic_code(),
1821 }
1822 }
1823
1824 #[must_use]
1826 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
1827 match self {
1828 Self::Executor(error) => error.diagnostic_detail(),
1829 Self::Store(error) => error.diagnostic_detail(),
1830 Self::Query(error) => error.diagnostic_detail(),
1831 Self::Recovery(error) => error.diagnostic_detail(),
1832 Self::Serialize(error) => error.diagnostic_detail(),
1833 }
1834 }
1835}
1836
1837impl ExecutorErrorDetail {
1838 #[must_use]
1840 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
1841 match self {
1842 Self::MutationRequiredFieldMissing => {
1843 diagnostic_code::DiagnosticCode::RuntimeUnsupported
1844 }
1845 }
1846 }
1847
1848 #[must_use]
1850 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
1851 match self {
1852 Self::MutationRequiredFieldMissing => {
1853 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
1854 boundary: diagnostic_code::RuntimeBoundaryCode::MutationRequiredFieldMissing,
1855 })
1856 }
1857 }
1858 }
1859}
1860
1861impl RecoveryErrorDetail {
1862 #[must_use]
1864 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
1865 match self {
1866 Self::UnsupportedFormatVersion { .. } => {
1867 diagnostic_code::DiagnosticCode::RuntimeIncompatiblePersistedFormat
1868 }
1869 Self::MalformedFormatMarker { .. } => {
1870 diagnostic_code::DiagnosticCode::RuntimeCorruption
1871 }
1872 }
1873 }
1874
1875 #[must_use]
1877 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
1878 let kind = match self {
1879 Self::UnsupportedFormatVersion { .. } => {
1880 diagnostic_code::RuntimeErrorKind::IncompatiblePersistedFormat
1881 }
1882 Self::MalformedFormatMarker { .. } => diagnostic_code::RuntimeErrorKind::Corruption,
1883 };
1884
1885 Some(diagnostic_code::DiagnosticDetail::RuntimeKind { kind })
1886 }
1887}
1888
1889impl SerializeErrorDetail {
1890 #[must_use]
1892 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
1893 match self {
1894 Self::PersistedRowLayoutOutsideAcceptedWindow | Self::PersistedRowSlotCountMismatch => {
1895 diagnostic_code::DiagnosticCode::RuntimeCorruption
1896 }
1897 }
1898 }
1899
1900 #[must_use]
1902 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
1903 let boundary = match self {
1904 Self::PersistedRowLayoutOutsideAcceptedWindow => {
1905 diagnostic_code::RuntimeBoundaryCode::PersistedRowLayoutOutsideAcceptedWindow
1906 }
1907 Self::PersistedRowSlotCountMismatch => {
1908 diagnostic_code::RuntimeBoundaryCode::PersistedRowSlotCountMismatch
1909 }
1910 };
1911
1912 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary { boundary })
1913 }
1914}
1915
1916impl StoreError {
1917 #[must_use]
1919 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
1920 match self {
1921 Self::NotFound => diagnostic_code::DiagnosticCode::StoreNotFound,
1922 Self::Corrupt => diagnostic_code::DiagnosticCode::StoreCorruption,
1923 Self::InvariantViolation => diagnostic_code::DiagnosticCode::StoreInvariantViolation,
1924 Self::SchemaDdlPublicationRaceLost
1925 | Self::SchemaDdlRewriteRequiresMigration
1926 | Self::SchemaRowLayoutVersionExhausted
1927 | Self::SchemaTransitionBudgetExceeded { .. }
1928 | Self::SchemaDdlSetNotNullValidationFailed => {
1929 diagnostic_code::DiagnosticCode::SchemaDdlAdmission
1930 }
1931 Self::JournalMutationRevisionExhausted | Self::SchemaGeneratedFieldAfterDdlField => {
1932 diagnostic_code::DiagnosticCode::RuntimeUnsupported
1933 }
1934 }
1935 }
1936
1937 #[must_use]
1939 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
1940 match self {
1941 Self::SchemaDdlPublicationRaceLost => {
1942 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
1943 reason: diagnostic_code::SchemaDdlAdmissionCode::PublicationRaceLost,
1944 })
1945 }
1946 Self::SchemaDdlRewriteRequiresMigration => {
1947 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
1948 reason: diagnostic_code::SchemaDdlAdmissionCode::SchemaRewriteRequiresMigration,
1949 })
1950 }
1951 Self::SchemaRowLayoutVersionExhausted => {
1952 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
1953 reason: diagnostic_code::SchemaDdlAdmissionCode::RowLayoutVersionExhausted,
1954 })
1955 }
1956 Self::JournalMutationRevisionExhausted => {
1957 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
1958 boundary:
1959 diagnostic_code::RuntimeBoundaryCode::JournalMutationRevisionExhausted,
1960 })
1961 }
1962 Self::SchemaTransitionBudgetExceeded { .. } => {
1963 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
1964 reason: diagnostic_code::SchemaDdlAdmissionCode::SchemaTransitionBudgetExceeded,
1965 })
1966 }
1967 Self::SchemaDdlSetNotNullValidationFailed => {
1968 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
1969 reason: diagnostic_code::SchemaDdlAdmissionCode::SetNotNullValidationFailed,
1970 })
1971 }
1972 Self::SchemaGeneratedFieldAfterDdlField => {
1973 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
1974 boundary: diagnostic_code::RuntimeBoundaryCode::GeneratedFieldAfterDdlField,
1975 })
1976 }
1977 Self::NotFound | Self::Corrupt | Self::InvariantViolation => None,
1978 }
1979 }
1980}
1981
1982impl QueryErrorDetail {
1983 #[must_use]
1985 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
1986 match self {
1987 Self::NumericOverflow => diagnostic_code::DiagnosticCode::QueryNumericOverflow,
1988 Self::NumericNotRepresentable => {
1989 diagnostic_code::DiagnosticCode::QueryNumericNotRepresentable
1990 }
1991 Self::UnsupportedSqlFeature { .. } => {
1992 diagnostic_code::DiagnosticCode::QueryUnsupportedSqlFeature
1993 }
1994 Self::SqlLowering { .. } => diagnostic_code::DiagnosticCode::QueryUnsupportedSqlFeature,
1995 Self::UnsupportedProjection { .. } => {
1996 diagnostic_code::DiagnosticCode::QueryUnsupportedProjection
1997 }
1998 Self::UnknownAggregateTargetField => {
1999 diagnostic_code::DiagnosticCode::QueryUnknownAggregateTargetField
2000 }
2001 Self::ResultShapeMismatch { .. } => {
2002 diagnostic_code::DiagnosticCode::QueryResultShapeMismatch
2003 }
2004 Self::QueryReadAdmission { .. } => diagnostic_code::DiagnosticCode::QueryReadAdmission,
2005 Self::SqlSurfaceMismatch { .. } => {
2006 diagnostic_code::DiagnosticCode::QuerySqlSurfaceMismatch
2007 }
2008 Self::SqlWriteBoundary { .. } => diagnostic_code::DiagnosticCode::QuerySqlWriteBoundary,
2009 Self::SchemaDdlAdmission { .. } => diagnostic_code::DiagnosticCode::SchemaDdlAdmission,
2010 Self::StaleSchemaRevision => diagnostic_code::DiagnosticCode::RuntimeConflict,
2011 }
2012 }
2013
2014 #[must_use]
2016 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2017 match self {
2018 Self::UnsupportedSqlFeature { feature } => {
2019 Some(diagnostic_code::DiagnosticDetail::UnsupportedSqlFeature { feature: *feature })
2020 }
2021 Self::SqlLowering { reason } => {
2022 Some(diagnostic_code::DiagnosticDetail::SqlLowering { reason: *reason })
2023 }
2024 Self::UnsupportedProjection { reason } => {
2025 Some(diagnostic_code::DiagnosticDetail::QueryProjection { reason: *reason })
2026 }
2027 Self::ResultShapeMismatch { reason } => {
2028 Some(diagnostic_code::DiagnosticDetail::QueryResultShape { reason: *reason })
2029 }
2030 Self::QueryReadAdmission { reason } => {
2031 Some(diagnostic_code::DiagnosticDetail::QueryReadAdmission { reason: *reason })
2032 }
2033 Self::SqlSurfaceMismatch { mismatch } => {
2034 Some(diagnostic_code::DiagnosticDetail::SqlSurfaceMismatch {
2035 mismatch: *mismatch,
2036 })
2037 }
2038 Self::SqlWriteBoundary { boundary } => {
2039 Some(diagnostic_code::DiagnosticDetail::SqlWriteBoundary {
2040 boundary: *boundary,
2041 })
2042 }
2043 Self::SchemaDdlAdmission { error } => {
2044 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2045 reason: error.diagnostic_code(),
2046 })
2047 }
2048 Self::NumericOverflow
2049 | Self::NumericNotRepresentable
2050 | Self::UnknownAggregateTargetField
2051 | Self::StaleSchemaRevision => None,
2052 }
2053 }
2054}
2055
2056impl SchemaDdlAdmissionError {
2057 #[must_use]
2059 pub const fn diagnostic_code(&self) -> diagnostic_code::SchemaDdlAdmissionCode {
2060 match self {
2061 Self::MissingExpectedSchemaVersion => {
2062 diagnostic_code::SchemaDdlAdmissionCode::MissingExpectedSchemaVersion
2063 }
2064 Self::MissingNextSchemaVersion => {
2065 diagnostic_code::SchemaDdlAdmissionCode::MissingNextSchemaVersion
2066 }
2067 Self::StaleExpectedSchemaVersion => {
2068 diagnostic_code::SchemaDdlAdmissionCode::StaleExpectedSchemaVersion
2069 }
2070 Self::InvalidExpectedSchemaVersion => {
2071 diagnostic_code::SchemaDdlAdmissionCode::InvalidExpectedSchemaVersion
2072 }
2073 Self::InvalidNextSchemaVersion => {
2074 diagnostic_code::SchemaDdlAdmissionCode::InvalidNextSchemaVersion
2075 }
2076 Self::AcceptedSchemaChangeWithoutVersionBump => {
2077 diagnostic_code::SchemaDdlAdmissionCode::AcceptedSchemaChangeWithoutVersionBump
2078 }
2079 Self::EmptyVersionBump => diagnostic_code::SchemaDdlAdmissionCode::EmptyVersionBump,
2080 Self::VersionGap => diagnostic_code::SchemaDdlAdmissionCode::VersionGap,
2081 Self::VersionRollback => diagnostic_code::SchemaDdlAdmissionCode::VersionRollback,
2082 Self::FingerprintMethodMismatch => {
2083 diagnostic_code::SchemaDdlAdmissionCode::FingerprintMethodMismatch
2084 }
2085 Self::UnsupportedTransitionClass => {
2086 diagnostic_code::SchemaDdlAdmissionCode::UnsupportedTransitionClass
2087 }
2088 Self::PhysicalRunnerMissing => {
2089 diagnostic_code::SchemaDdlAdmissionCode::PhysicalRunnerMissing
2090 }
2091 Self::ValidationFailed => diagnostic_code::SchemaDdlAdmissionCode::ValidationFailed,
2092 Self::PublicationRaceLost => {
2093 diagnostic_code::SchemaDdlAdmissionCode::PublicationRaceLost
2094 }
2095 Self::InvalidAddColumnDefault => {
2096 diagnostic_code::SchemaDdlAdmissionCode::InvalidAddColumnDefault
2097 }
2098 Self::InvalidAlterColumnDefault => {
2099 diagnostic_code::SchemaDdlAdmissionCode::InvalidAlterColumnDefault
2100 }
2101 Self::GeneratedIndexDropRejected => {
2102 diagnostic_code::SchemaDdlAdmissionCode::GeneratedIndexDropRejected
2103 }
2104 Self::SchemaRewriteRequiresMigration => {
2105 diagnostic_code::SchemaDdlAdmissionCode::SchemaRewriteRequiresMigration
2106 }
2107 Self::SchemaTransitionBudgetExceeded { .. } => {
2108 diagnostic_code::SchemaDdlAdmissionCode::SchemaTransitionBudgetExceeded
2109 }
2110 Self::GeneratedFieldDefaultChangeRejected => {
2111 diagnostic_code::SchemaDdlAdmissionCode::GeneratedFieldDefaultChangeRejected
2112 }
2113 Self::GeneratedFieldNullabilityChangeRejected => {
2114 diagnostic_code::SchemaDdlAdmissionCode::GeneratedFieldNullabilityChangeRejected
2115 }
2116 Self::SetNotNullValidationFailed => {
2117 diagnostic_code::SchemaDdlAdmissionCode::SetNotNullValidationFailed
2118 }
2119 Self::RowLayoutVersionExhausted => {
2120 diagnostic_code::SchemaDdlAdmissionCode::RowLayoutVersionExhausted
2121 }
2122 }
2123 }
2124}
2125
2126#[repr(u8)]
2133#[derive(Clone, Copy, Eq, PartialEq)]
2134pub enum ErrorClass {
2135 Corruption,
2136 IncompatiblePersistedFormat,
2137 NotFound,
2138 Internal,
2139 Conflict,
2140 Unsupported,
2141 InvariantViolation,
2142}
2143
2144impl ErrorClass {
2145 #[must_use]
2147 pub const fn diagnostic_code(self, origin: ErrorOrigin) -> diagnostic_code::DiagnosticCode {
2148 match self {
2149 Self::Corruption if matches!(origin, ErrorOrigin::Store) => {
2150 diagnostic_code::DiagnosticCode::StoreCorruption
2151 }
2152 Self::Corruption => diagnostic_code::DiagnosticCode::RuntimeCorruption,
2153 Self::IncompatiblePersistedFormat => {
2154 diagnostic_code::DiagnosticCode::RuntimeIncompatiblePersistedFormat
2155 }
2156 Self::NotFound if matches!(origin, ErrorOrigin::Store) => {
2157 diagnostic_code::DiagnosticCode::StoreNotFound
2158 }
2159 Self::NotFound => diagnostic_code::DiagnosticCode::RuntimeNotFound,
2160 Self::Internal => diagnostic_code::DiagnosticCode::RuntimeInternal,
2161 Self::Conflict => diagnostic_code::DiagnosticCode::RuntimeConflict,
2162 Self::Unsupported if matches!(origin, ErrorOrigin::Cursor) => {
2163 diagnostic_code::DiagnosticCode::QueryInvalidContinuationCursor
2164 }
2165 Self::Unsupported => diagnostic_code::DiagnosticCode::RuntimeUnsupported,
2166 Self::InvariantViolation if matches!(origin, ErrorOrigin::Store) => {
2167 diagnostic_code::DiagnosticCode::StoreInvariantViolation
2168 }
2169 Self::InvariantViolation => diagnostic_code::DiagnosticCode::RuntimeInvariantViolation,
2170 }
2171 }
2172}
2173
2174impl fmt::Debug for ErrorClass {
2175 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2176 write!(f, "{}", *self as u8)
2177 }
2178}
2179
2180#[repr(u8)]
2187#[derive(Clone, Copy, Eq, PartialEq)]
2188pub enum ErrorOrigin {
2189 Serialize,
2190 Store,
2191 Index,
2192 Identity,
2193 Query,
2194 Planner,
2195 Cursor,
2196 Recovery,
2197 Response,
2198 Executor,
2199 Interface,
2200}
2201
2202impl ErrorOrigin {
2203 #[must_use]
2205 pub const fn diagnostic_origin(self) -> diagnostic_code::ErrorOrigin {
2206 match self {
2207 Self::Serialize => diagnostic_code::ErrorOrigin::Serialize,
2208 Self::Store => diagnostic_code::ErrorOrigin::Store,
2209 Self::Index => diagnostic_code::ErrorOrigin::Index,
2210 Self::Identity => diagnostic_code::ErrorOrigin::Identity,
2211 Self::Query => diagnostic_code::ErrorOrigin::Query,
2212 Self::Planner => diagnostic_code::ErrorOrigin::Planner,
2213 Self::Cursor => diagnostic_code::ErrorOrigin::Cursor,
2214 Self::Recovery => diagnostic_code::ErrorOrigin::Recovery,
2215 Self::Response => diagnostic_code::ErrorOrigin::Response,
2216 Self::Executor => diagnostic_code::ErrorOrigin::Executor,
2217 Self::Interface => diagnostic_code::ErrorOrigin::Interface,
2218 }
2219 }
2220}
2221
2222impl fmt::Debug for ErrorOrigin {
2223 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2224 write!(f, "{}", *self as u8)
2225 }
2226}