1#[cfg(test)]
9mod tests;
10
11use icydb_diagnostic_code as diagnostic_code;
12use std::fmt;
13use thiserror::Error as ThisError;
14
15const COMPACT_QUERY_DIAGNOSTIC_MESSAGE: &str = "query diagnostic";
16const COMPACT_RUNTIME_DIAGNOSTIC_MESSAGE: &str = "runtime diagnostic";
17const COMPACT_SCHEMA_DDL_STORE_MESSAGE: &str = "schema DDL diagnostic";
18const COMPACT_STORE_DIAGNOSTIC_MESSAGE: &str = "store diagnostic";
19const COMPACT_INDEX_DIAGNOSTIC_MESSAGE: &str = "index diagnostic";
20const COMPACT_SERIALIZE_DIAGNOSTIC_MESSAGE: &str = "serialize diagnostic";
21const COMPACT_IDENTITY_DIAGNOSTIC_MESSAGE: &str = "identity diagnostic";
22
23const fn compact_message_for(_class: ErrorClass, origin: ErrorOrigin) -> &'static str {
24 match origin {
25 ErrorOrigin::Serialize => COMPACT_SERIALIZE_DIAGNOSTIC_MESSAGE,
26 ErrorOrigin::Store => COMPACT_STORE_DIAGNOSTIC_MESSAGE,
27 ErrorOrigin::Index => COMPACT_INDEX_DIAGNOSTIC_MESSAGE,
28 ErrorOrigin::Identity => COMPACT_IDENTITY_DIAGNOSTIC_MESSAGE,
29 ErrorOrigin::Query | ErrorOrigin::Planner | ErrorOrigin::Response => {
30 COMPACT_QUERY_DIAGNOSTIC_MESSAGE
31 }
32 ErrorOrigin::Cursor
33 | ErrorOrigin::Recovery
34 | ErrorOrigin::Executor
35 | ErrorOrigin::Interface => COMPACT_RUNTIME_DIAGNOSTIC_MESSAGE,
36 }
37}
38
39#[derive(Debug, ThisError)]
140#[error("{message}")]
141pub struct InternalError {
142 pub(crate) class: ErrorClass,
143 pub(crate) origin: ErrorOrigin,
144 pub(crate) message: String,
145
146 pub(crate) detail: Option<ErrorDetail>,
149}
150
151impl InternalError {
152 #[cold]
156 #[inline(never)]
157 pub fn new(class: ErrorClass, origin: ErrorOrigin, _message: impl Into<String>) -> Self {
158 let message = compact_message_for(class, origin);
159
160 let detail = match (class, origin) {
161 (ErrorClass::Corruption, ErrorOrigin::Store) => {
162 Some(ErrorDetail::Store(StoreError::Corrupt {
163 message: message.to_string(),
164 }))
165 }
166 (ErrorClass::InvariantViolation, ErrorOrigin::Store) => {
167 Some(ErrorDetail::Store(StoreError::InvariantViolation {
168 message: message.to_string(),
169 }))
170 }
171 _ => None,
172 };
173
174 Self {
175 class,
176 origin,
177 message: message.to_string(),
178 detail,
179 }
180 }
181
182 #[must_use]
184 pub const fn class(&self) -> ErrorClass {
185 self.class
186 }
187
188 #[must_use]
190 pub const fn origin(&self) -> ErrorOrigin {
191 self.origin
192 }
193
194 #[must_use]
196 pub fn message(&self) -> &str {
197 &self.message
198 }
199
200 #[must_use]
202 pub const fn detail(&self) -> Option<&ErrorDetail> {
203 self.detail.as_ref()
204 }
205
206 #[must_use]
208 pub fn diagnostic(&self) -> diagnostic_code::Diagnostic {
209 diagnostic_code::Diagnostic::new(
210 self.diagnostic_code(),
211 self.origin.diagnostic_origin(),
212 self.detail
213 .as_ref()
214 .and_then(ErrorDetail::diagnostic_detail),
215 )
216 }
217
218 #[must_use]
220 pub fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
221 self.detail.as_ref().map_or_else(
222 || self.class.diagnostic_code(self.origin),
223 ErrorDetail::diagnostic_code,
224 )
225 }
226
227 #[must_use]
229 pub fn into_message(self) -> String {
230 self.message
231 }
232
233 #[cold]
235 #[inline(never)]
236 pub(crate) fn classified(
237 class: ErrorClass,
238 origin: ErrorOrigin,
239 message: impl Into<String>,
240 ) -> Self {
241 Self::new(class, origin, message)
242 }
243
244 #[cold]
246 #[inline(never)]
247 pub(crate) fn with_message(self, _message: impl Into<String>) -> Self {
248 self
249 }
250
251 #[cold]
255 #[inline(never)]
256 pub(crate) fn with_origin(self, origin: ErrorOrigin) -> Self {
257 Self::classified(self.class, origin, "")
258 }
259
260 #[cold]
262 #[inline(never)]
263 pub(crate) fn index_invariant(_message: impl Into<String>) -> Self {
264 Self::new(
265 ErrorClass::InvariantViolation,
266 ErrorOrigin::Index,
267 COMPACT_INDEX_DIAGNOSTIC_MESSAGE,
268 )
269 }
270
271 pub(crate) fn index_key_field_count_exceeds_max(
273 _index_name: &str,
274 _field_count: usize,
275 _max_fields: usize,
276 ) -> Self {
277 Self::index_invariant(COMPACT_INDEX_DIAGNOSTIC_MESSAGE)
278 }
279
280 pub(crate) fn index_key_item_field_missing_on_entity_model(_field: &str) -> Self {
282 Self::index_invariant(COMPACT_INDEX_DIAGNOSTIC_MESSAGE)
283 }
284
285 pub(crate) fn index_key_item_field_missing_on_lookup_row(_field: &str) -> Self {
287 Self::index_invariant(COMPACT_INDEX_DIAGNOSTIC_MESSAGE)
288 }
289
290 pub(crate) fn index_expression_source_type_mismatch(
292 _index_name: &str,
293 _expression: impl fmt::Display,
294 _expected: &str,
295 _source_label: &str,
296 ) -> Self {
297 Self::index_invariant(COMPACT_INDEX_DIAGNOSTIC_MESSAGE)
298 }
299
300 #[cold]
303 #[inline(never)]
304 pub(crate) fn planner_executor_invariant(_reason: impl Into<String>) -> Self {
305 Self::new(
306 ErrorClass::InvariantViolation,
307 ErrorOrigin::Planner,
308 COMPACT_RUNTIME_DIAGNOSTIC_MESSAGE,
309 )
310 }
311
312 #[cold]
315 #[inline(never)]
316 pub(crate) fn query_executor_invariant(_reason: impl Into<String>) -> Self {
317 Self::new(
318 ErrorClass::InvariantViolation,
319 ErrorOrigin::Query,
320 COMPACT_QUERY_DIAGNOSTIC_MESSAGE,
321 )
322 }
323
324 #[cold]
327 #[inline(never)]
328 pub(crate) fn cursor_executor_invariant(_reason: impl Into<String>) -> Self {
329 Self::new(
330 ErrorClass::InvariantViolation,
331 ErrorOrigin::Cursor,
332 COMPACT_RUNTIME_DIAGNOSTIC_MESSAGE,
333 )
334 }
335
336 #[cold]
338 #[inline(never)]
339 pub(crate) fn executor_invariant(_message: impl Into<String>) -> Self {
340 Self::new(
341 ErrorClass::InvariantViolation,
342 ErrorOrigin::Executor,
343 COMPACT_RUNTIME_DIAGNOSTIC_MESSAGE,
344 )
345 }
346
347 #[cold]
349 #[inline(never)]
350 pub(crate) fn executor_internal(_message: impl Into<String>) -> Self {
351 Self::new(
352 ErrorClass::Internal,
353 ErrorOrigin::Executor,
354 COMPACT_RUNTIME_DIAGNOSTIC_MESSAGE,
355 )
356 }
357
358 #[cold]
360 #[inline(never)]
361 pub(crate) fn executor_unsupported(_message: impl Into<String>) -> Self {
362 Self::new(
363 ErrorClass::Unsupported,
364 ErrorOrigin::Executor,
365 COMPACT_RUNTIME_DIAGNOSTIC_MESSAGE,
366 )
367 }
368
369 pub(crate) fn mutation_entity_primary_key_missing(
371 _entity_path: &str,
372 _field_name: &str,
373 ) -> Self {
374 Self::executor_invariant(COMPACT_RUNTIME_DIAGNOSTIC_MESSAGE)
375 }
376
377 pub(crate) fn mutation_entity_primary_key_invalid_value(
379 _entity_path: &str,
380 _field_name: &str,
381 _value: &crate::value::Value,
382 ) -> Self {
383 Self::executor_invariant(COMPACT_RUNTIME_DIAGNOSTIC_MESSAGE)
384 }
385
386 pub(crate) fn mutation_entity_primary_key_type_mismatch(
388 _entity_path: &str,
389 _field_name: &str,
390 _value: &crate::value::Value,
391 ) -> Self {
392 Self::executor_invariant(COMPACT_RUNTIME_DIAGNOSTIC_MESSAGE)
393 }
394
395 pub(crate) fn mutation_entity_primary_key_mismatch(
397 _entity_path: &str,
398 _field_name: &str,
399 _field_value: &crate::value::Value,
400 _identity_key: &crate::value::Value,
401 ) -> Self {
402 Self::executor_invariant(COMPACT_RUNTIME_DIAGNOSTIC_MESSAGE)
403 }
404
405 pub(crate) fn mutation_entity_field_missing(
407 _entity_path: &str,
408 _field_name: &str,
409 _indexed: bool,
410 ) -> Self {
411 Self::executor_invariant(COMPACT_RUNTIME_DIAGNOSTIC_MESSAGE)
412 }
413
414 pub(crate) fn mutation_structural_patch_required_field_missing(
416 _entity_path: &str,
417 _field_name: &str,
418 ) -> Self {
419 Self::executor_invariant(COMPACT_RUNTIME_DIAGNOSTIC_MESSAGE)
420 }
421
422 pub(crate) fn mutation_entity_field_type_mismatch(
424 _entity_path: &str,
425 _field_name: &str,
426 _value: &crate::value::Value,
427 ) -> Self {
428 Self::executor_invariant(COMPACT_RUNTIME_DIAGNOSTIC_MESSAGE)
429 }
430
431 pub(crate) fn mutation_generated_field_explicit(_entity_path: &str, _field_name: &str) -> Self {
433 Self::executor_unsupported(COMPACT_RUNTIME_DIAGNOSTIC_MESSAGE)
434 }
435
436 #[must_use]
438 pub fn mutation_create_missing_authored_fields(_entity_path: &str, _field_names: &str) -> Self {
439 Self::executor_unsupported(COMPACT_RUNTIME_DIAGNOSTIC_MESSAGE)
440 }
441
442 pub(crate) fn mutation_structural_after_image_invalid(
447 _entity_path: &str,
448 _data_key: impl fmt::Display,
449 _detail: impl AsRef<str>,
450 ) -> Self {
451 Self::executor_invariant(COMPACT_RUNTIME_DIAGNOSTIC_MESSAGE)
452 }
453
454 pub(crate) fn mutation_structural_field_unknown(_entity_path: &str, _field_name: &str) -> Self {
456 Self::executor_invariant(COMPACT_RUNTIME_DIAGNOSTIC_MESSAGE)
457 }
458
459 pub(crate) fn mutation_decimal_scale_mismatch(
461 _entity_path: &str,
462 _field_name: &str,
463 _expected_scale: impl fmt::Display,
464 _actual_scale: impl fmt::Display,
465 ) -> Self {
466 Self::executor_unsupported(COMPACT_RUNTIME_DIAGNOSTIC_MESSAGE)
467 }
468
469 pub(crate) fn mutation_text_max_len_exceeded(
471 _entity_path: &str,
472 _field_name: &str,
473 _max_len: impl fmt::Display,
474 _actual_len: impl fmt::Display,
475 ) -> Self {
476 Self::executor_unsupported(COMPACT_RUNTIME_DIAGNOSTIC_MESSAGE)
477 }
478
479 pub(crate) fn mutation_set_field_list_required(_entity_path: &str, _field_name: &str) -> Self {
481 Self::executor_invariant(COMPACT_RUNTIME_DIAGNOSTIC_MESSAGE)
482 }
483
484 pub(crate) fn mutation_set_field_not_canonical(_entity_path: &str, _field_name: &str) -> Self {
486 Self::executor_invariant(COMPACT_RUNTIME_DIAGNOSTIC_MESSAGE)
487 }
488
489 pub(crate) fn mutation_map_field_map_required(_entity_path: &str, _field_name: &str) -> Self {
491 Self::executor_invariant(COMPACT_RUNTIME_DIAGNOSTIC_MESSAGE)
492 }
493
494 pub(crate) fn mutation_map_field_entries_invalid(
496 _entity_path: &str,
497 _field_name: &str,
498 _detail: impl fmt::Display,
499 ) -> Self {
500 Self::executor_invariant(COMPACT_RUNTIME_DIAGNOSTIC_MESSAGE)
501 }
502
503 pub(crate) fn mutation_map_field_entries_not_canonical(
505 _entity_path: &str,
506 _field_name: &str,
507 ) -> Self {
508 Self::executor_invariant(COMPACT_RUNTIME_DIAGNOSTIC_MESSAGE)
509 }
510
511 pub(crate) fn scalar_page_ordering_after_filtering_required() -> Self {
513 Self::query_executor_invariant(COMPACT_QUERY_DIAGNOSTIC_MESSAGE)
514 }
515
516 pub(crate) fn scalar_page_cursor_boundary_order_required() -> Self {
518 Self::query_executor_invariant(COMPACT_QUERY_DIAGNOSTIC_MESSAGE)
519 }
520
521 pub(crate) fn scalar_page_cursor_boundary_after_ordering_required() -> Self {
523 Self::query_executor_invariant(COMPACT_QUERY_DIAGNOSTIC_MESSAGE)
524 }
525
526 pub(crate) fn scalar_page_pagination_after_ordering_required() -> Self {
528 Self::query_executor_invariant(COMPACT_QUERY_DIAGNOSTIC_MESSAGE)
529 }
530
531 pub(crate) fn scalar_page_delete_limit_after_ordering_required() -> Self {
533 Self::query_executor_invariant(COMPACT_QUERY_DIAGNOSTIC_MESSAGE)
534 }
535
536 pub(crate) fn load_runtime_scalar_payload_required() -> Self {
538 Self::query_executor_invariant(COMPACT_QUERY_DIAGNOSTIC_MESSAGE)
539 }
540
541 pub(crate) fn load_runtime_grouped_payload_required() -> Self {
543 Self::query_executor_invariant(COMPACT_QUERY_DIAGNOSTIC_MESSAGE)
544 }
545
546 pub(crate) fn load_runtime_scalar_surface_payload_required() -> Self {
548 Self::query_executor_invariant(COMPACT_QUERY_DIAGNOSTIC_MESSAGE)
549 }
550
551 pub(crate) fn load_runtime_grouped_surface_payload_required() -> Self {
553 Self::query_executor_invariant(COMPACT_QUERY_DIAGNOSTIC_MESSAGE)
554 }
555
556 pub(crate) fn load_executor_load_plan_required() -> Self {
558 Self::query_executor_invariant(COMPACT_QUERY_DIAGNOSTIC_MESSAGE)
559 }
560
561 pub(crate) fn delete_executor_grouped_unsupported() -> Self {
563 Self::executor_unsupported(COMPACT_RUNTIME_DIAGNOSTIC_MESSAGE)
564 }
565
566 pub(crate) fn delete_executor_delete_plan_required() -> Self {
568 Self::query_executor_invariant(COMPACT_QUERY_DIAGNOSTIC_MESSAGE)
569 }
570
571 pub(crate) fn aggregate_fold_mode_terminal_contract_required() -> Self {
573 Self::query_executor_invariant(COMPACT_QUERY_DIAGNOSTIC_MESSAGE)
574 }
575
576 pub(crate) fn fast_stream_route_kind_request_match_required() -> Self {
578 Self::query_executor_invariant(COMPACT_QUERY_DIAGNOSTIC_MESSAGE)
579 }
580
581 pub(crate) fn secondary_index_prefix_spec_required() -> Self {
583 Self::query_executor_invariant(COMPACT_QUERY_DIAGNOSTIC_MESSAGE)
584 }
585
586 pub(crate) fn index_range_limit_spec_required() -> Self {
588 Self::query_executor_invariant(COMPACT_QUERY_DIAGNOSTIC_MESSAGE)
589 }
590
591 pub(crate) fn mutation_atomic_save_duplicate_key(
593 _entity_path: &str,
594 _key: impl fmt::Display,
595 ) -> Self {
596 Self::executor_unsupported(COMPACT_RUNTIME_DIAGNOSTIC_MESSAGE)
597 }
598
599 pub(crate) fn mutation_index_store_generation_changed(
601 _expected_generation: u64,
602 _observed_generation: u64,
603 ) -> Self {
604 Self::executor_invariant(COMPACT_RUNTIME_DIAGNOSTIC_MESSAGE)
605 }
606
607 #[cold]
609 #[inline(never)]
610 pub(crate) fn planner_invariant(_message: impl Into<String>) -> Self {
611 Self::new(
612 ErrorClass::InvariantViolation,
613 ErrorOrigin::Planner,
614 COMPACT_RUNTIME_DIAGNOSTIC_MESSAGE,
615 )
616 }
617
618 pub(crate) fn query_invalid_logical_plan(_reason: impl Into<String>) -> Self {
620 Self::planner_invariant(COMPACT_RUNTIME_DIAGNOSTIC_MESSAGE)
621 }
622
623 pub(crate) fn store_invariant() -> Self {
625 Self::new(
626 ErrorClass::InvariantViolation,
627 ErrorOrigin::Store,
628 COMPACT_STORE_DIAGNOSTIC_MESSAGE,
629 )
630 }
631
632 pub(crate) fn duplicate_runtime_hooks_for_entity_tag(
634 _entity_tag: crate::types::EntityTag,
635 ) -> Self {
636 Self::store_invariant()
637 }
638
639 pub(crate) fn duplicate_runtime_hooks_for_entity_path(_entity_path: &str) -> Self {
641 Self::store_invariant()
642 }
643
644 #[cold]
646 #[inline(never)]
647 pub(crate) fn store_internal(_message: impl Into<String>) -> Self {
648 Self::new(
649 ErrorClass::Internal,
650 ErrorOrigin::Store,
651 COMPACT_STORE_DIAGNOSTIC_MESSAGE,
652 )
653 }
654
655 pub(crate) fn commit_memory_id_unconfigured() -> Self {
657 Self::store_internal(
658 "commit memory id is not configured; initialize recovery before commit store access",
659 )
660 }
661
662 pub(crate) fn commit_memory_id_mismatch(_cached_id: u8, _configured_id: u8) -> Self {
664 Self::store_internal(COMPACT_STORE_DIAGNOSTIC_MESSAGE)
665 }
666
667 pub(crate) fn commit_memory_stable_key_mismatch(
669 _cached_key: &str,
670 _configured_key: &str,
671 ) -> Self {
672 Self::store_internal(COMPACT_STORE_DIAGNOSTIC_MESSAGE)
673 }
674
675 pub(crate) fn delete_rollback_row_required() -> Self {
677 Self::store_internal("missing raw row for delete rollback")
678 }
679
680 pub(crate) fn recovery_integrity_validation_failed(
682 _missing_index_entries: u64,
683 _divergent_index_entries: u64,
684 _orphan_index_references: u64,
685 ) -> Self {
686 Self::store_corruption()
687 }
688
689 #[cold]
691 #[inline(never)]
692 pub(crate) fn index_internal(_message: impl Into<String>) -> Self {
693 Self::new(
694 ErrorClass::Internal,
695 ErrorOrigin::Index,
696 COMPACT_INDEX_DIAGNOSTIC_MESSAGE,
697 )
698 }
699
700 pub(crate) fn structural_index_removal_entity_key_required() -> Self {
702 Self::index_internal("missing old entity key for structural index removal")
703 }
704
705 pub(crate) fn structural_index_insertion_entity_key_required() -> Self {
707 Self::index_internal("missing new entity key for structural index insertion")
708 }
709
710 pub(crate) fn index_commit_op_old_entity_key_required() -> Self {
712 Self::index_internal("missing old entity key for index removal")
713 }
714
715 pub(crate) fn index_commit_op_new_entity_key_required() -> Self {
717 Self::index_internal("missing new entity key for index insertion")
718 }
719
720 #[cfg(test)]
722 pub(crate) fn query_internal(message: impl Into<String>) -> Self {
723 Self::new(ErrorClass::Internal, ErrorOrigin::Query, message.into())
724 }
725
726 #[cold]
728 #[inline(never)]
729 pub(crate) fn query_unsupported(_message: impl Into<String>) -> Self {
730 Self::new(
731 ErrorClass::Unsupported,
732 ErrorOrigin::Query,
733 COMPACT_QUERY_DIAGNOSTIC_MESSAGE,
734 )
735 }
736
737 #[cold]
739 #[inline(never)]
740 #[cfg(feature = "sql")]
741 pub(crate) fn query_schema_ddl_admission(error: SchemaDdlAdmissionError) -> Self {
742 Self {
743 class: ErrorClass::Unsupported,
744 origin: ErrorOrigin::Query,
745 message: COMPACT_QUERY_DIAGNOSTIC_MESSAGE.to_string(),
746 detail: Some(ErrorDetail::Query(QueryErrorDetail::SchemaDdlAdmission {
747 error,
748 })),
749 }
750 }
751
752 #[cold]
754 #[inline(never)]
755 pub(crate) fn query_numeric_overflow() -> Self {
756 Self {
757 class: ErrorClass::Unsupported,
758 origin: ErrorOrigin::Query,
759 message: COMPACT_QUERY_DIAGNOSTIC_MESSAGE.to_string(),
760 detail: Some(ErrorDetail::Query(QueryErrorDetail::NumericOverflow)),
761 }
762 }
763
764 #[cold]
767 #[inline(never)]
768 pub(crate) fn query_numeric_not_representable() -> Self {
769 Self {
770 class: ErrorClass::Unsupported,
771 origin: ErrorOrigin::Query,
772 message: COMPACT_QUERY_DIAGNOSTIC_MESSAGE.to_string(),
773 detail: Some(ErrorDetail::Query(
774 QueryErrorDetail::NumericNotRepresentable,
775 )),
776 }
777 }
778
779 #[cold]
781 #[inline(never)]
782 pub(crate) fn serialize_internal(_message: impl Into<String>) -> Self {
783 Self::new(
784 ErrorClass::Internal,
785 ErrorOrigin::Serialize,
786 COMPACT_SERIALIZE_DIAGNOSTIC_MESSAGE,
787 )
788 }
789
790 pub(crate) fn persisted_row_encode_failed(_detail: impl fmt::Display) -> Self {
792 Self::persisted_row_encode_internal()
793 }
794
795 pub(crate) fn persisted_row_encode_internal() -> Self {
797 Self::serialize_internal("row encode failed")
798 }
799
800 pub(crate) fn persisted_row_field_encode_failed(
802 field_name: &str,
803 _detail: impl fmt::Display,
804 ) -> Self {
805 Self::persisted_row_field_encode_internal(field_name)
806 }
807
808 pub(crate) fn persisted_row_field_encode_internal(_field_name: &str) -> Self {
810 Self::persisted_row_encode_internal()
811 }
812
813 pub(crate) fn bytes_field_value_encode_failed(_detail: impl fmt::Display) -> Self {
815 Self::serialize_internal(COMPACT_SERIALIZE_DIAGNOSTIC_MESSAGE)
816 }
817
818 #[cold]
820 #[inline(never)]
821 pub(crate) fn store_corruption() -> Self {
822 Self::new(
823 ErrorClass::Corruption,
824 ErrorOrigin::Store,
825 COMPACT_STORE_DIAGNOSTIC_MESSAGE,
826 )
827 }
828
829 pub(crate) fn commit_corruption(_detail: impl fmt::Display) -> Self {
831 Self::store_corruption()
832 }
833
834 pub(crate) fn commit_component_corruption(
836 _component: &str,
837 _detail: impl fmt::Display,
838 ) -> Self {
839 Self::commit_corruption(COMPACT_STORE_DIAGNOSTIC_MESSAGE)
840 }
841
842 pub(crate) fn commit_id_generation_failed(_detail: impl fmt::Display) -> Self {
844 Self::store_internal(COMPACT_STORE_DIAGNOSTIC_MESSAGE)
845 }
846
847 pub(crate) fn commit_marker_payload_exceeds_u32_length_limit(
849 _label: &str,
850 _len: usize,
851 ) -> Self {
852 Self::store_unsupported()
853 }
854
855 pub(crate) fn commit_component_length_invalid(
857 _component: &str,
858 _len: usize,
859 _expected: impl fmt::Display,
860 ) -> Self {
861 Self::commit_corruption(COMPACT_STORE_DIAGNOSTIC_MESSAGE)
862 }
863
864 pub(crate) fn commit_marker_exceeds_max_size(_size: usize, _max_size: u32) -> Self {
866 Self::commit_corruption(COMPACT_STORE_DIAGNOSTIC_MESSAGE)
867 }
868
869 pub(crate) fn commit_control_slot_exceeds_max_size(_size: usize, _max_size: u32) -> Self {
871 Self::store_unsupported()
872 }
873
874 pub(crate) fn commit_control_slot_marker_bytes_exceed_u32_length_limit(_size: usize) -> Self {
876 Self::store_unsupported()
877 }
878
879 pub(crate) fn startup_index_rebuild_invalid_data_key(
881 _store_path: &str,
882 _detail: impl fmt::Display,
883 ) -> Self {
884 Self::store_corruption()
885 }
886
887 #[cold]
889 #[inline(never)]
890 pub(crate) fn index_corruption(_message: impl Into<String>) -> Self {
891 Self::new(
892 ErrorClass::Corruption,
893 ErrorOrigin::Index,
894 COMPACT_INDEX_DIAGNOSTIC_MESSAGE,
895 )
896 }
897
898 pub(crate) fn index_unique_validation_corruption() -> Self {
900 Self::index_plan_index_corruption("unique index corrupted")
901 }
902
903 pub(crate) fn structural_index_entry_corruption() -> Self {
905 Self::index_plan_index_corruption("index entry corrupted")
906 }
907
908 pub(crate) fn index_unique_validation_entity_key_required() -> Self {
910 Self::index_invariant("missing entity key during unique validation")
911 }
912
913 pub(crate) fn index_unique_validation_row_deserialize_failed() -> Self {
915 Self::index_plan_serialize_corruption("unique row decode failed")
916 }
917
918 pub(crate) fn index_unique_validation_primary_key_decode_failed() -> Self {
920 Self::index_plan_serialize_corruption("unique primary key decode failed")
921 }
922
923 pub(crate) fn index_unique_validation_key_rebuild_failed() -> Self {
925 Self::index_plan_serialize_corruption("unique key rebuild failed")
926 }
927
928 pub(crate) fn index_unique_validation_row_required() -> Self {
930 Self::index_plan_store_corruption()
931 }
932
933 pub(crate) fn index_only_predicate_component_required() -> Self {
935 Self::index_invariant("index-only predicate program referenced missing index component")
936 }
937
938 pub(crate) fn index_scan_continuation_anchor_within_envelope_required() -> Self {
940 Self::index_invariant(
941 "index-range continuation anchor is outside the requested range envelope",
942 )
943 }
944
945 pub(crate) fn index_scan_continuation_advancement_required() -> Self {
947 Self::index_invariant("index-range continuation scan did not advance beyond the anchor")
948 }
949
950 pub(crate) fn index_scan_key_corrupted_during(
952 _context: &'static str,
953 _err: impl fmt::Display,
954 ) -> Self {
955 Self::index_corruption("index key corrupted")
956 }
957
958 pub(crate) fn index_projection_component_required(
960 _index_name: &str,
961 _component_index: usize,
962 ) -> Self {
963 Self::index_invariant(COMPACT_INDEX_DIAGNOSTIC_MESSAGE)
964 }
965
966 pub(crate) fn index_entry_decode_failed(_err: impl fmt::Display) -> Self {
968 Self::index_corruption("index entry decode failed")
969 }
970
971 pub(crate) fn serialize_corruption(_message: impl Into<String>) -> Self {
973 Self::new(
974 ErrorClass::Corruption,
975 ErrorOrigin::Serialize,
976 COMPACT_SERIALIZE_DIAGNOSTIC_MESSAGE,
977 )
978 }
979
980 pub(crate) fn persisted_row_decode_failed(_detail: impl fmt::Display) -> Self {
982 Self::persisted_row_decode_corruption()
983 }
984
985 pub(crate) fn persisted_row_decode_corruption() -> Self {
987 Self::serialize_corruption("row decode failed")
988 }
989
990 pub(crate) fn persisted_row_field_decode_failed(
992 field_name: &str,
993 _detail: impl fmt::Display,
994 ) -> Self {
995 Self::persisted_row_field_decode_corruption(field_name)
996 }
997
998 pub(crate) fn persisted_row_field_decode_corruption(_field_name: &str) -> Self {
1000 Self::persisted_row_decode_corruption()
1001 }
1002
1003 pub(crate) fn persisted_row_field_kind_decode_failed(
1005 field_name: &str,
1006 _field_kind: impl fmt::Debug,
1007 _detail: impl fmt::Display,
1008 ) -> Self {
1009 Self::persisted_row_field_decode_corruption(field_name)
1010 }
1011
1012 pub(crate) fn persisted_row_field_payload_exact_len_required(field_name: &str) -> Self {
1014 Self::persisted_row_field_decode_corruption(field_name)
1015 }
1016
1017 pub(crate) fn persisted_row_field_payload_must_be_empty(field_name: &str) -> Self {
1019 Self::persisted_row_field_decode_corruption(field_name)
1020 }
1021
1022 pub(crate) fn persisted_row_field_payload_invalid_byte(field_name: &str) -> Self {
1024 Self::persisted_row_field_decode_corruption(field_name)
1025 }
1026
1027 pub(crate) fn persisted_row_field_payload_non_finite(field_name: &str) -> Self {
1029 Self::persisted_row_field_decode_corruption(field_name)
1030 }
1031
1032 pub(crate) fn persisted_row_field_payload_out_of_range(field_name: &str) -> Self {
1034 Self::persisted_row_field_decode_corruption(field_name)
1035 }
1036
1037 pub(crate) fn persisted_row_field_text_payload_invalid_utf8(field_name: &str) -> Self {
1039 Self::persisted_row_field_decode_corruption(field_name)
1040 }
1041
1042 pub(crate) fn persisted_row_slot_lookup_out_of_bounds(_model_path: &str, _slot: usize) -> Self {
1044 Self::index_invariant(COMPACT_INDEX_DIAGNOSTIC_MESSAGE)
1045 }
1046
1047 pub(crate) fn persisted_row_slot_cache_lookup_out_of_bounds(
1049 _model_path: &str,
1050 _slot: usize,
1051 ) -> Self {
1052 Self::index_invariant(COMPACT_INDEX_DIAGNOSTIC_MESSAGE)
1053 }
1054
1055 pub(crate) fn persisted_row_primary_key_not_primary_key_encodable(
1057 _data_key: impl fmt::Debug,
1058 _detail: impl fmt::Display,
1059 ) -> Self {
1060 Self::persisted_row_decode_corruption()
1061 }
1062
1063 pub(crate) fn persisted_row_primary_key_slot_missing(_data_key: impl fmt::Debug) -> Self {
1065 Self::persisted_row_decode_corruption()
1066 }
1067
1068 pub(crate) fn persisted_row_key_mismatch() -> Self {
1070 Self::store_corruption()
1071 }
1072
1073 pub(crate) fn persisted_row_declared_field_missing(field_name: &str) -> Self {
1075 Self::persisted_row_field_decode_corruption(field_name)
1076 }
1077
1078 pub(crate) fn data_key_entity_mismatch() -> Self {
1080 Self::store_corruption()
1081 }
1082
1083 pub(crate) fn reverse_index_ordinal_overflow(
1085 _source_path: &str,
1086 _field_name: &str,
1087 _target_path: &str,
1088 _detail: impl fmt::Display,
1089 ) -> Self {
1090 Self::index_internal(COMPACT_INDEX_DIAGNOSTIC_MESSAGE)
1091 }
1092
1093 pub(crate) fn reverse_index_entry_corrupted(
1095 _source_path: &str,
1096 _field_name: &str,
1097 _target_path: &str,
1098 _index_key: impl fmt::Debug,
1099 _detail: impl fmt::Display,
1100 ) -> Self {
1101 Self::index_corruption(COMPACT_INDEX_DIAGNOSTIC_MESSAGE)
1102 }
1103
1104 pub(crate) fn relation_target_store_missing(
1106 _source_path: &str,
1107 _field_name: &str,
1108 _target_path: &str,
1109 _store_path: &str,
1110 _detail: impl fmt::Display,
1111 ) -> Self {
1112 Self::executor_internal(COMPACT_RUNTIME_DIAGNOSTIC_MESSAGE)
1113 }
1114
1115 pub(crate) fn relation_target_key_decode_failed(
1117 _context_label: &str,
1118 _source_path: &str,
1119 _field_name: &str,
1120 _target_path: &str,
1121 _detail: impl fmt::Display,
1122 ) -> Self {
1123 Self::identity_corruption(COMPACT_IDENTITY_DIAGNOSTIC_MESSAGE)
1124 }
1125
1126 pub(crate) fn relation_target_entity_mismatch(
1128 _context_label: &str,
1129 _source_path: &str,
1130 _field_name: &str,
1131 _target_path: &str,
1132 _target_entity_name: &str,
1133 _expected_tag: impl fmt::Display,
1134 _actual_tag: impl fmt::Display,
1135 ) -> Self {
1136 Self::store_corruption()
1137 }
1138
1139 pub(crate) fn relation_source_row_decode_failed(
1141 _source_path: &str,
1142 _field_name: &str,
1143 _target_path: &str,
1144 _detail: impl fmt::Display,
1145 ) -> Self {
1146 Self::persisted_row_decode_corruption()
1147 }
1148
1149 pub(crate) fn relation_source_row_unsupported_scalar_relation_key(
1151 _source_path: &str,
1152 _field_name: &str,
1153 _target_path: &str,
1154 ) -> Self {
1155 Self::persisted_row_decode_corruption()
1156 }
1157
1158 pub(crate) fn relation_source_row_unsupported_key_kind(_field_kind: impl fmt::Debug) -> Self {
1160 Self::persisted_row_decode_corruption()
1161 }
1162
1163 pub(crate) fn reverse_index_relation_target_decode_invariant_violated(
1165 _source_path: &str,
1166 _field_name: &str,
1167 _target_path: &str,
1168 ) -> Self {
1169 Self::executor_internal(COMPACT_RUNTIME_DIAGNOSTIC_MESSAGE)
1170 }
1171
1172 pub(crate) fn bytes_covering_component_payload_empty() -> Self {
1174 Self::index_corruption("covering component corrupted")
1175 }
1176
1177 pub(crate) fn bytes_covering_bool_payload_truncated() -> Self {
1179 Self::index_corruption("covering component corrupted")
1180 }
1181
1182 pub(crate) fn bytes_covering_component_payload_invalid_length(_payload_kind: &str) -> Self {
1184 Self::index_corruption("covering component corrupted")
1185 }
1186
1187 pub(crate) fn bytes_covering_bool_payload_invalid_value() -> Self {
1189 Self::index_corruption("covering component corrupted")
1190 }
1191
1192 pub(crate) fn bytes_covering_text_payload_invalid_terminator() -> Self {
1194 Self::index_corruption("covering component corrupted")
1195 }
1196
1197 pub(crate) fn bytes_covering_text_payload_trailing_bytes() -> Self {
1199 Self::index_corruption("covering component corrupted")
1200 }
1201
1202 pub(crate) fn bytes_covering_text_payload_invalid_utf8() -> Self {
1204 Self::index_corruption("covering component corrupted")
1205 }
1206
1207 pub(crate) fn bytes_covering_text_payload_invalid_escape_byte() -> Self {
1209 Self::index_corruption("covering component corrupted")
1210 }
1211
1212 pub(crate) fn bytes_covering_text_payload_missing_terminator() -> Self {
1214 Self::index_corruption("covering component corrupted")
1215 }
1216
1217 #[must_use]
1219 pub fn missing_persisted_slot(field_name: &'static str) -> Self {
1220 Self::persisted_row_field_decode_corruption(field_name)
1221 }
1222
1223 pub(crate) fn identity_corruption(_message: impl Into<String>) -> Self {
1225 Self::new(
1226 ErrorClass::Corruption,
1227 ErrorOrigin::Identity,
1228 COMPACT_IDENTITY_DIAGNOSTIC_MESSAGE,
1229 )
1230 }
1231
1232 #[cold]
1234 #[inline(never)]
1235 pub(crate) fn store_unsupported() -> Self {
1236 Self::new(
1237 ErrorClass::Unsupported,
1238 ErrorOrigin::Store,
1239 COMPACT_STORE_DIAGNOSTIC_MESSAGE,
1240 )
1241 }
1242
1243 pub(crate) fn schema_ddl_publication_race_lost(entity_path: &'static str) -> Self {
1245 Self {
1246 class: ErrorClass::Unsupported,
1247 origin: ErrorOrigin::Store,
1248 message: COMPACT_SCHEMA_DDL_STORE_MESSAGE.to_string(),
1249 detail: Some(ErrorDetail::Store(
1250 StoreError::SchemaDdlPublicationRaceLost {
1251 entity_path: entity_path.to_string(),
1252 },
1253 )),
1254 }
1255 }
1256
1257 #[cfg(feature = "sql")]
1259 pub(crate) fn schema_ddl_set_not_null_validation_failed(
1260 entity_path: &'static str,
1261 column_name: &str,
1262 ) -> Self {
1263 Self {
1264 class: ErrorClass::Unsupported,
1265 origin: ErrorOrigin::Store,
1266 message: COMPACT_SCHEMA_DDL_STORE_MESSAGE.to_string(),
1267 detail: Some(ErrorDetail::Store(
1268 StoreError::SchemaDdlSetNotNullValidationFailed {
1269 entity_path: entity_path.to_string(),
1270 column_name: column_name.to_string(),
1271 },
1272 )),
1273 }
1274 }
1275
1276 pub(crate) fn unsupported_entity_tag_in_data_store(
1278 _entity_tag: crate::types::EntityTag,
1279 ) -> Self {
1280 Self::store_unsupported()
1281 }
1282
1283 #[cfg_attr(test, expect(dead_code))]
1285 pub(crate) fn commit_memory_id_registration_failed(_err: impl fmt::Display) -> Self {
1286 Self::store_internal(COMPACT_STORE_DIAGNOSTIC_MESSAGE)
1287 }
1288
1289 pub(crate) fn index_unsupported(_message: impl Into<String>) -> Self {
1291 Self::new(
1292 ErrorClass::Unsupported,
1293 ErrorOrigin::Index,
1294 COMPACT_INDEX_DIAGNOSTIC_MESSAGE,
1295 )
1296 }
1297
1298 pub(crate) fn index_component_exceeds_max_size(
1300 _key_item: impl fmt::Display,
1301 _len: usize,
1302 _max_component_size: usize,
1303 ) -> Self {
1304 Self::index_unsupported(COMPACT_INDEX_DIAGNOSTIC_MESSAGE)
1305 }
1306
1307 pub(crate) fn serialize_unsupported(_message: impl Into<String>) -> Self {
1309 Self::new(
1310 ErrorClass::Unsupported,
1311 ErrorOrigin::Serialize,
1312 COMPACT_SERIALIZE_DIAGNOSTIC_MESSAGE,
1313 )
1314 }
1315
1316 pub(crate) fn cursor_unsupported(_message: impl Into<String>) -> Self {
1318 Self::new(
1319 ErrorClass::Unsupported,
1320 ErrorOrigin::Cursor,
1321 COMPACT_RUNTIME_DIAGNOSTIC_MESSAGE,
1322 )
1323 }
1324
1325 pub(crate) fn serialize_incompatible_persisted_format(_message: impl Into<String>) -> Self {
1327 Self::new(
1328 ErrorClass::IncompatiblePersistedFormat,
1329 ErrorOrigin::Serialize,
1330 COMPACT_SERIALIZE_DIAGNOSTIC_MESSAGE,
1331 )
1332 }
1333
1334 #[cfg(feature = "sql")]
1337 pub(crate) fn query_unsupported_sql_feature(feature: diagnostic_code::SqlFeatureCode) -> Self {
1338 Self {
1339 class: ErrorClass::Unsupported,
1340 origin: ErrorOrigin::Query,
1341 message: COMPACT_QUERY_DIAGNOSTIC_MESSAGE.to_string(),
1342 detail: Some(ErrorDetail::Query(
1343 QueryErrorDetail::UnsupportedSqlFeature { feature },
1344 )),
1345 }
1346 }
1347
1348 #[cfg(feature = "sql")]
1351 pub(crate) fn query_sql_lowering(reason: diagnostic_code::SqlLoweringCode) -> Self {
1352 Self {
1353 class: ErrorClass::Unsupported,
1354 origin: ErrorOrigin::Query,
1355 message: COMPACT_QUERY_DIAGNOSTIC_MESSAGE.to_string(),
1356 detail: Some(ErrorDetail::Query(QueryErrorDetail::SqlLowering { reason })),
1357 }
1358 }
1359
1360 pub(crate) fn query_unsupported_projection(
1363 reason: diagnostic_code::QueryProjectionCode,
1364 ) -> Self {
1365 Self {
1366 class: ErrorClass::Unsupported,
1367 origin: ErrorOrigin::Query,
1368 message: COMPACT_QUERY_DIAGNOSTIC_MESSAGE.to_string(),
1369 detail: Some(ErrorDetail::Query(
1370 QueryErrorDetail::UnsupportedProjection { reason },
1371 )),
1372 }
1373 }
1374
1375 pub(crate) fn query_unknown_aggregate_target_field() -> Self {
1377 Self {
1378 class: ErrorClass::Unsupported,
1379 origin: ErrorOrigin::Query,
1380 message: COMPACT_QUERY_DIAGNOSTIC_MESSAGE.to_string(),
1381 detail: Some(ErrorDetail::Query(
1382 QueryErrorDetail::UnknownAggregateTargetField,
1383 )),
1384 }
1385 }
1386
1387 pub(crate) fn query_result_shape_mismatch(
1390 reason: diagnostic_code::QueryResultShapeCode,
1391 ) -> Self {
1392 Self {
1393 class: ErrorClass::Unsupported,
1394 origin: ErrorOrigin::Query,
1395 message: COMPACT_QUERY_DIAGNOSTIC_MESSAGE.to_string(),
1396 detail: Some(ErrorDetail::Query(QueryErrorDetail::ResultShapeMismatch {
1397 reason,
1398 })),
1399 }
1400 }
1401
1402 #[cfg(feature = "sql")]
1405 pub(crate) fn query_sql_surface_mismatch(
1406 mismatch: diagnostic_code::SqlSurfaceMismatchCode,
1407 ) -> Self {
1408 Self {
1409 class: ErrorClass::Unsupported,
1410 origin: ErrorOrigin::Query,
1411 message: COMPACT_QUERY_DIAGNOSTIC_MESSAGE.to_string(),
1412 detail: Some(ErrorDetail::Query(QueryErrorDetail::SqlSurfaceMismatch {
1413 mismatch,
1414 })),
1415 }
1416 }
1417
1418 #[cfg(feature = "sql")]
1420 pub(crate) fn query_sql_write_boundary(
1421 boundary: diagnostic_code::SqlWriteBoundaryCode,
1422 ) -> Self {
1423 Self {
1424 class: ErrorClass::Unsupported,
1425 origin: ErrorOrigin::Query,
1426 message: COMPACT_QUERY_DIAGNOSTIC_MESSAGE.to_string(),
1427 detail: Some(ErrorDetail::Query(QueryErrorDetail::SqlWriteBoundary {
1428 boundary,
1429 })),
1430 }
1431 }
1432
1433 pub fn store_not_found(key: impl Into<String>) -> Self {
1434 let key = key.into();
1435
1436 Self {
1437 class: ErrorClass::NotFound,
1438 origin: ErrorOrigin::Store,
1439 message: COMPACT_STORE_DIAGNOSTIC_MESSAGE.to_string(),
1440 detail: Some(ErrorDetail::Store(StoreError::NotFound { key })),
1441 }
1442 }
1443
1444 pub fn unsupported_entity_path(_path: impl Into<String>) -> Self {
1446 Self::store_unsupported()
1447 }
1448
1449 #[must_use]
1450 pub const fn is_not_found(&self) -> bool {
1451 matches!(
1452 self.detail,
1453 Some(ErrorDetail::Store(StoreError::NotFound { .. }))
1454 )
1455 }
1456
1457 #[must_use]
1458 pub fn display_with_class(&self) -> String {
1459 format!("{}:{}: {}", self.origin, self.class, self.message)
1460 }
1461
1462 #[cold]
1464 #[inline(never)]
1465 pub(crate) fn index_plan_corruption(origin: ErrorOrigin, _message: impl Into<String>) -> Self {
1466 let message = match origin {
1467 ErrorOrigin::Index => COMPACT_INDEX_DIAGNOSTIC_MESSAGE,
1468 ErrorOrigin::Store => COMPACT_STORE_DIAGNOSTIC_MESSAGE,
1469 ErrorOrigin::Serialize => COMPACT_SERIALIZE_DIAGNOSTIC_MESSAGE,
1470 _ => COMPACT_RUNTIME_DIAGNOSTIC_MESSAGE,
1471 };
1472 Self::new(ErrorClass::Corruption, origin, message)
1473 }
1474
1475 #[cold]
1477 #[inline(never)]
1478 pub(crate) fn index_plan_index_corruption(message: impl Into<String>) -> Self {
1479 Self::index_plan_corruption(ErrorOrigin::Index, message)
1480 }
1481
1482 #[cold]
1484 #[inline(never)]
1485 pub(crate) fn index_plan_store_corruption() -> Self {
1486 Self::index_plan_corruption(ErrorOrigin::Store, COMPACT_STORE_DIAGNOSTIC_MESSAGE)
1487 }
1488
1489 #[cold]
1491 #[inline(never)]
1492 pub(crate) fn index_plan_serialize_corruption(message: impl Into<String>) -> Self {
1493 Self::index_plan_corruption(ErrorOrigin::Serialize, message)
1494 }
1495
1496 #[cfg(test)]
1498 pub(crate) fn index_plan_invariant(origin: ErrorOrigin, _message: impl Into<String>) -> Self {
1499 Self::new(
1500 ErrorClass::InvariantViolation,
1501 origin,
1502 compact_message_for(ErrorClass::InvariantViolation, origin),
1503 )
1504 }
1505
1506 #[cfg(test)]
1508 pub(crate) fn index_plan_store_invariant() -> Self {
1509 Self::index_plan_invariant(ErrorOrigin::Store, COMPACT_STORE_DIAGNOSTIC_MESSAGE)
1510 }
1511
1512 pub(crate) fn index_violation(_path: &str, _index_fields: &[&str]) -> Self {
1514 Self::new(
1515 ErrorClass::Conflict,
1516 ErrorOrigin::Index,
1517 COMPACT_INDEX_DIAGNOSTIC_MESSAGE,
1518 )
1519 }
1520}
1521
1522#[derive(ThisError)]
1530pub enum ErrorDetail {
1531 #[error("{0}")]
1532 Store(StoreError),
1533 #[error("{0}")]
1534 Query(QueryErrorDetail),
1535 }
1542
1543#[derive(ThisError)]
1551pub enum StoreError {
1552 #[error("key not found: {key}")]
1553 NotFound { key: String },
1554
1555 #[error("store corruption: {message}")]
1556 Corrupt { message: String },
1557
1558 #[error("store invariant violation: {message}")]
1559 InvariantViolation { message: String },
1560
1561 #[error("schema DDL diagnostic")]
1562 SchemaDdlPublicationRaceLost { entity_path: String },
1563
1564 #[error("schema DDL diagnostic")]
1565 SchemaDdlSetNotNullValidationFailed {
1566 entity_path: String,
1567 column_name: String,
1568 },
1569}
1570
1571pub enum QueryErrorDetail {
1578 NumericOverflow,
1579
1580 NumericNotRepresentable,
1581
1582 UnsupportedSqlFeature {
1583 feature: diagnostic_code::SqlFeatureCode,
1584 },
1585
1586 SqlLowering {
1587 reason: diagnostic_code::SqlLoweringCode,
1588 },
1589
1590 UnsupportedProjection {
1591 reason: diagnostic_code::QueryProjectionCode,
1592 },
1593
1594 UnknownAggregateTargetField,
1595
1596 ResultShapeMismatch {
1597 reason: diagnostic_code::QueryResultShapeCode,
1598 },
1599
1600 SqlSurfaceMismatch {
1601 mismatch: diagnostic_code::SqlSurfaceMismatchCode,
1602 },
1603
1604 SqlWriteBoundary {
1605 boundary: diagnostic_code::SqlWriteBoundaryCode,
1606 },
1607
1608 SchemaDdlAdmission {
1609 error: SchemaDdlAdmissionError,
1610 },
1611}
1612
1613impl fmt::Display for QueryErrorDetail {
1614 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1615 f.write_str(COMPACT_QUERY_DIAGNOSTIC_MESSAGE)
1616 }
1617}
1618
1619impl std::error::Error for QueryErrorDetail {}
1620
1621#[derive(Clone, Copy, Eq, PartialEq)]
1630pub enum SchemaDdlAdmissionError {
1631 MissingExpectedSchemaVersion,
1632
1633 MissingNextSchemaVersion,
1634
1635 StaleExpectedSchemaVersion,
1636
1637 InvalidExpectedSchemaVersion,
1638
1639 InvalidNextSchemaVersion,
1640
1641 AcceptedSchemaChangeWithoutVersionBump,
1642
1643 EmptyVersionBump,
1644
1645 VersionGap,
1646
1647 VersionRollback,
1648
1649 FingerprintMethodMismatch,
1650
1651 UnsupportedTransitionClass,
1652
1653 PhysicalRunnerMissing,
1654
1655 ValidationFailed,
1656
1657 PublicationRaceLost,
1658
1659 InvalidAddColumnDefault,
1660
1661 InvalidAlterColumnDefault,
1662
1663 GeneratedIndexDropRejected,
1664
1665 RequiredDropDefaultUnsupported,
1666
1667 GeneratedFieldDefaultChangeRejected,
1668
1669 GeneratedFieldNullabilityChangeRejected,
1670
1671 SetNotNullValidationFailed,
1672}
1673
1674impl fmt::Display for SchemaDdlAdmissionError {
1675 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1676 f.write_str("schema DDL admission")
1677 }
1678}
1679
1680impl std::error::Error for SchemaDdlAdmissionError {}
1681
1682impl fmt::Debug for ErrorDetail {
1683 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1684 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
1685 }
1686}
1687
1688impl fmt::Debug for StoreError {
1689 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1690 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
1691 }
1692}
1693
1694impl fmt::Debug for QueryErrorDetail {
1695 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1696 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
1697 }
1698}
1699
1700impl fmt::Debug for SchemaDdlAdmissionError {
1701 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1702 fmt_compact_diagnostic(
1703 f,
1704 diagnostic_code::DiagnosticCode::SchemaDdlAdmission,
1705 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
1706 reason: self.diagnostic_code(),
1707 }),
1708 )
1709 }
1710}
1711
1712fn fmt_compact_diagnostic(
1713 f: &mut fmt::Formatter<'_>,
1714 code: diagnostic_code::DiagnosticCode,
1715 detail: Option<diagnostic_code::DiagnosticDetail>,
1716) -> fmt::Result {
1717 write!(
1718 f,
1719 "{}",
1720 diagnostic_code::ErrorCode::from_parts(code, detail).raw()
1721 )
1722}
1723
1724impl ErrorDetail {
1725 #[must_use]
1727 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
1728 match self {
1729 Self::Store(error) => error.diagnostic_code(),
1730 Self::Query(error) => error.diagnostic_code(),
1731 }
1732 }
1733
1734 #[must_use]
1736 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
1737 match self {
1738 Self::Store(error) => error.diagnostic_detail(),
1739 Self::Query(error) => error.diagnostic_detail(),
1740 }
1741 }
1742}
1743
1744impl StoreError {
1745 #[must_use]
1747 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
1748 match self {
1749 Self::NotFound { .. } => diagnostic_code::DiagnosticCode::StoreNotFound,
1750 Self::Corrupt { .. } => diagnostic_code::DiagnosticCode::StoreCorruption,
1751 Self::InvariantViolation { .. } => {
1752 diagnostic_code::DiagnosticCode::StoreInvariantViolation
1753 }
1754 Self::SchemaDdlPublicationRaceLost { .. }
1755 | Self::SchemaDdlSetNotNullValidationFailed { .. } => {
1756 diagnostic_code::DiagnosticCode::SchemaDdlAdmission
1757 }
1758 }
1759 }
1760
1761 #[must_use]
1763 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
1764 match self {
1765 Self::SchemaDdlPublicationRaceLost { .. } => {
1766 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
1767 reason: diagnostic_code::SchemaDdlAdmissionCode::PublicationRaceLost,
1768 })
1769 }
1770 Self::SchemaDdlSetNotNullValidationFailed { .. } => {
1771 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
1772 reason: diagnostic_code::SchemaDdlAdmissionCode::SetNotNullValidationFailed,
1773 })
1774 }
1775 Self::NotFound { .. } | Self::Corrupt { .. } | Self::InvariantViolation { .. } => None,
1776 }
1777 }
1778}
1779
1780impl QueryErrorDetail {
1781 #[must_use]
1783 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
1784 match self {
1785 Self::NumericOverflow => diagnostic_code::DiagnosticCode::QueryNumericOverflow,
1786 Self::NumericNotRepresentable => {
1787 diagnostic_code::DiagnosticCode::QueryNumericNotRepresentable
1788 }
1789 Self::UnsupportedSqlFeature { .. } => {
1790 diagnostic_code::DiagnosticCode::QueryUnsupportedSqlFeature
1791 }
1792 Self::SqlLowering { .. } => diagnostic_code::DiagnosticCode::QueryUnsupportedSqlFeature,
1793 Self::UnsupportedProjection { .. } => {
1794 diagnostic_code::DiagnosticCode::QueryUnsupportedProjection
1795 }
1796 Self::UnknownAggregateTargetField => {
1797 diagnostic_code::DiagnosticCode::QueryUnknownAggregateTargetField
1798 }
1799 Self::ResultShapeMismatch { .. } => {
1800 diagnostic_code::DiagnosticCode::QueryResultShapeMismatch
1801 }
1802 Self::SqlSurfaceMismatch { .. } => {
1803 diagnostic_code::DiagnosticCode::QuerySqlSurfaceMismatch
1804 }
1805 Self::SqlWriteBoundary { .. } => diagnostic_code::DiagnosticCode::QuerySqlWriteBoundary,
1806 Self::SchemaDdlAdmission { .. } => diagnostic_code::DiagnosticCode::SchemaDdlAdmission,
1807 }
1808 }
1809
1810 #[must_use]
1812 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
1813 match self {
1814 Self::UnsupportedSqlFeature { feature } => {
1815 Some(diagnostic_code::DiagnosticDetail::UnsupportedSqlFeature { feature: *feature })
1816 }
1817 Self::SqlLowering { reason } => {
1818 Some(diagnostic_code::DiagnosticDetail::SqlLowering { reason: *reason })
1819 }
1820 Self::UnsupportedProjection { reason } => {
1821 Some(diagnostic_code::DiagnosticDetail::QueryProjection { reason: *reason })
1822 }
1823 Self::ResultShapeMismatch { reason } => {
1824 Some(diagnostic_code::DiagnosticDetail::QueryResultShape { reason: *reason })
1825 }
1826 Self::SqlSurfaceMismatch { mismatch } => {
1827 Some(diagnostic_code::DiagnosticDetail::SqlSurfaceMismatch {
1828 mismatch: *mismatch,
1829 })
1830 }
1831 Self::SqlWriteBoundary { boundary } => {
1832 Some(diagnostic_code::DiagnosticDetail::SqlWriteBoundary {
1833 boundary: *boundary,
1834 })
1835 }
1836 Self::SchemaDdlAdmission { error } => {
1837 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
1838 reason: error.diagnostic_code(),
1839 })
1840 }
1841 Self::NumericOverflow
1842 | Self::NumericNotRepresentable
1843 | Self::UnknownAggregateTargetField => None,
1844 }
1845 }
1846}
1847
1848impl SchemaDdlAdmissionError {
1849 #[must_use]
1851 pub const fn diagnostic_code(&self) -> diagnostic_code::SchemaDdlAdmissionCode {
1852 match self {
1853 Self::MissingExpectedSchemaVersion => {
1854 diagnostic_code::SchemaDdlAdmissionCode::MissingExpectedSchemaVersion
1855 }
1856 Self::MissingNextSchemaVersion => {
1857 diagnostic_code::SchemaDdlAdmissionCode::MissingNextSchemaVersion
1858 }
1859 Self::StaleExpectedSchemaVersion => {
1860 diagnostic_code::SchemaDdlAdmissionCode::StaleExpectedSchemaVersion
1861 }
1862 Self::InvalidExpectedSchemaVersion => {
1863 diagnostic_code::SchemaDdlAdmissionCode::InvalidExpectedSchemaVersion
1864 }
1865 Self::InvalidNextSchemaVersion => {
1866 diagnostic_code::SchemaDdlAdmissionCode::InvalidNextSchemaVersion
1867 }
1868 Self::AcceptedSchemaChangeWithoutVersionBump => {
1869 diagnostic_code::SchemaDdlAdmissionCode::AcceptedSchemaChangeWithoutVersionBump
1870 }
1871 Self::EmptyVersionBump => diagnostic_code::SchemaDdlAdmissionCode::EmptyVersionBump,
1872 Self::VersionGap => diagnostic_code::SchemaDdlAdmissionCode::VersionGap,
1873 Self::VersionRollback => diagnostic_code::SchemaDdlAdmissionCode::VersionRollback,
1874 Self::FingerprintMethodMismatch => {
1875 diagnostic_code::SchemaDdlAdmissionCode::FingerprintMethodMismatch
1876 }
1877 Self::UnsupportedTransitionClass => {
1878 diagnostic_code::SchemaDdlAdmissionCode::UnsupportedTransitionClass
1879 }
1880 Self::PhysicalRunnerMissing => {
1881 diagnostic_code::SchemaDdlAdmissionCode::PhysicalRunnerMissing
1882 }
1883 Self::ValidationFailed => diagnostic_code::SchemaDdlAdmissionCode::ValidationFailed,
1884 Self::PublicationRaceLost => {
1885 diagnostic_code::SchemaDdlAdmissionCode::PublicationRaceLost
1886 }
1887 Self::InvalidAddColumnDefault => {
1888 diagnostic_code::SchemaDdlAdmissionCode::InvalidAddColumnDefault
1889 }
1890 Self::InvalidAlterColumnDefault => {
1891 diagnostic_code::SchemaDdlAdmissionCode::InvalidAlterColumnDefault
1892 }
1893 Self::GeneratedIndexDropRejected => {
1894 diagnostic_code::SchemaDdlAdmissionCode::GeneratedIndexDropRejected
1895 }
1896 Self::RequiredDropDefaultUnsupported => {
1897 diagnostic_code::SchemaDdlAdmissionCode::RequiredDropDefaultUnsupported
1898 }
1899 Self::GeneratedFieldDefaultChangeRejected => {
1900 diagnostic_code::SchemaDdlAdmissionCode::GeneratedFieldDefaultChangeRejected
1901 }
1902 Self::GeneratedFieldNullabilityChangeRejected => {
1903 diagnostic_code::SchemaDdlAdmissionCode::GeneratedFieldNullabilityChangeRejected
1904 }
1905 Self::SetNotNullValidationFailed => {
1906 diagnostic_code::SchemaDdlAdmissionCode::SetNotNullValidationFailed
1907 }
1908 }
1909 }
1910}
1911
1912#[repr(u16)]
1919#[derive(Clone, Copy, Eq, PartialEq)]
1920pub enum ErrorClass {
1921 Corruption,
1922 IncompatiblePersistedFormat,
1923 NotFound,
1924 Internal,
1925 Conflict,
1926 Unsupported,
1927 InvariantViolation,
1928}
1929
1930impl ErrorClass {
1931 #[must_use]
1933 pub const fn diagnostic_code(self, origin: ErrorOrigin) -> diagnostic_code::DiagnosticCode {
1934 match self {
1935 Self::Corruption if matches!(origin, ErrorOrigin::Store) => {
1936 diagnostic_code::DiagnosticCode::StoreCorruption
1937 }
1938 Self::Corruption => diagnostic_code::DiagnosticCode::RuntimeCorruption,
1939 Self::IncompatiblePersistedFormat => {
1940 diagnostic_code::DiagnosticCode::RuntimeIncompatiblePersistedFormat
1941 }
1942 Self::NotFound if matches!(origin, ErrorOrigin::Store) => {
1943 diagnostic_code::DiagnosticCode::StoreNotFound
1944 }
1945 Self::NotFound => diagnostic_code::DiagnosticCode::RuntimeNotFound,
1946 Self::Internal => diagnostic_code::DiagnosticCode::RuntimeInternal,
1947 Self::Conflict => diagnostic_code::DiagnosticCode::RuntimeConflict,
1948 Self::Unsupported => diagnostic_code::DiagnosticCode::RuntimeUnsupported,
1949 Self::InvariantViolation if matches!(origin, ErrorOrigin::Store) => {
1950 diagnostic_code::DiagnosticCode::StoreInvariantViolation
1951 }
1952 Self::InvariantViolation => diagnostic_code::DiagnosticCode::RuntimeInvariantViolation,
1953 }
1954 }
1955}
1956
1957impl fmt::Display for ErrorClass {
1958 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1959 let label = match self {
1960 Self::Corruption => "corruption",
1961 Self::IncompatiblePersistedFormat => "incompatible_persisted_format",
1962 Self::NotFound => "not_found",
1963 Self::Internal => "internal",
1964 Self::Conflict => "conflict",
1965 Self::Unsupported => "unsupported",
1966 Self::InvariantViolation => "invariant_violation",
1967 };
1968 write!(f, "{label}")
1969 }
1970}
1971
1972impl fmt::Debug for ErrorClass {
1973 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1974 write!(f, "{}", *self as u16)
1975 }
1976}
1977
1978#[repr(u16)]
1985#[derive(Clone, Copy, Eq, PartialEq)]
1986pub enum ErrorOrigin {
1987 Serialize,
1988 Store,
1989 Index,
1990 Identity,
1991 Query,
1992 Planner,
1993 Cursor,
1994 Recovery,
1995 Response,
1996 Executor,
1997 Interface,
1998}
1999
2000impl ErrorOrigin {
2001 #[must_use]
2003 pub const fn diagnostic_origin(self) -> diagnostic_code::ErrorOrigin {
2004 match self {
2005 Self::Serialize => diagnostic_code::ErrorOrigin::Serialize,
2006 Self::Store => diagnostic_code::ErrorOrigin::Store,
2007 Self::Index => diagnostic_code::ErrorOrigin::Index,
2008 Self::Identity => diagnostic_code::ErrorOrigin::Identity,
2009 Self::Query => diagnostic_code::ErrorOrigin::Query,
2010 Self::Planner => diagnostic_code::ErrorOrigin::Planner,
2011 Self::Cursor => diagnostic_code::ErrorOrigin::Cursor,
2012 Self::Recovery => diagnostic_code::ErrorOrigin::Recovery,
2013 Self::Response => diagnostic_code::ErrorOrigin::Response,
2014 Self::Executor => diagnostic_code::ErrorOrigin::Executor,
2015 Self::Interface => diagnostic_code::ErrorOrigin::Interface,
2016 }
2017 }
2018}
2019
2020impl fmt::Display for ErrorOrigin {
2021 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2022 let label = match self {
2023 Self::Serialize => "serialize",
2024 Self::Store => "store",
2025 Self::Index => "index",
2026 Self::Identity => "identity",
2027 Self::Query => "query",
2028 Self::Planner => "planner",
2029 Self::Cursor => "cursor",
2030 Self::Recovery => "recovery",
2031 Self::Response => "response",
2032 Self::Executor => "executor",
2033 Self::Interface => "interface",
2034 };
2035 write!(f, "{label}")
2036 }
2037}
2038
2039impl fmt::Debug for ErrorOrigin {
2040 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2041 write!(f, "{}", *self as u16)
2042 }
2043}