1#[cfg(test)]
9mod tests;
10
11use candid::CandidType;
12use icydb_diagnostic_code as diagnostic_code;
13use serde::Deserialize;
14use std::fmt;
15
16pub(crate) const COMPACT_QUERY_DIAGNOSTIC_MESSAGE: &str = "query diagnostic";
17const COMPACT_RUNTIME_DIAGNOSTIC_MESSAGE: &str = "runtime diagnostic";
18const COMPACT_STORE_DIAGNOSTIC_MESSAGE: &str = "store diagnostic";
19const COMPACT_INDEX_DIAGNOSTIC_MESSAGE: &str = "index diagnostic";
20const COMPACT_SERIALIZE_DIAGNOSTIC_MESSAGE: &str = "serialize diagnostic";
21const COMPACT_IDENTITY_DIAGNOSTIC_MESSAGE: &str = "identity diagnostic";
22
23const fn compact_message_for(_class: ErrorClass, origin: ErrorOrigin) -> &'static str {
24 match origin {
25 ErrorOrigin::Serialize => COMPACT_SERIALIZE_DIAGNOSTIC_MESSAGE,
26 ErrorOrigin::Store => COMPACT_STORE_DIAGNOSTIC_MESSAGE,
27 ErrorOrigin::Index => COMPACT_INDEX_DIAGNOSTIC_MESSAGE,
28 ErrorOrigin::Identity => COMPACT_IDENTITY_DIAGNOSTIC_MESSAGE,
29 ErrorOrigin::Query | ErrorOrigin::Planner | ErrorOrigin::Response => {
30 COMPACT_QUERY_DIAGNOSTIC_MESSAGE
31 }
32 ErrorOrigin::Cursor
33 | ErrorOrigin::Recovery
34 | ErrorOrigin::Executor
35 | ErrorOrigin::Interface => COMPACT_RUNTIME_DIAGNOSTIC_MESSAGE,
36 }
37}
38
39#[derive(Clone, Copy, Debug)]
134pub(crate) struct MutationDiagnosticContext {
135 entity_tag: u64,
136 operation: diagnostic_code::DiagnosticMutationOperation,
137 batch_position: Option<u32>,
138}
139
140impl MutationDiagnosticContext {
141 #[must_use]
143 pub(crate) const fn new(
144 entity_tag: u64,
145 operation: diagnostic_code::DiagnosticMutationOperation,
146 batch_position: u32,
147 ) -> Self {
148 Self {
149 entity_tag,
150 operation,
151 batch_position: Some(batch_position),
152 }
153 }
154
155 #[must_use]
157 pub(crate) const fn operation_only(
158 entity_tag: u64,
159 operation: diagnostic_code::DiagnosticMutationOperation,
160 ) -> Self {
161 Self {
162 entity_tag,
163 operation,
164 batch_position: None,
165 }
166 }
167
168 fn facts(self, field_id: Option<u32>) -> Vec<(diagnostic_code::DiagnosticFactTag, u64)> {
169 let mut facts = Vec::with_capacity(
170 2 + usize::from(field_id.is_some()) + usize::from(self.batch_position.is_some()),
171 );
172 facts.push((
173 diagnostic_code::DiagnosticFactTag::EntityTag,
174 self.entity_tag,
175 ));
176 if let Some(field_id) = field_id {
177 facts.push((
178 diagnostic_code::DiagnosticFactTag::FieldId,
179 u64::from(field_id),
180 ));
181 }
182 facts.push((
183 diagnostic_code::DiagnosticFactTag::MutationOperation,
184 self.operation.raw(),
185 ));
186 if let Some(batch_position) = self.batch_position {
187 facts.push((
188 diagnostic_code::DiagnosticFactTag::BatchPosition,
189 u64::from(batch_position),
190 ));
191 }
192 facts
193 }
194
195 #[must_use]
196 pub(crate) const fn entity_tag(self) -> u64 {
197 self.entity_tag
198 }
199
200 fn append_operation_facts(self, facts: &mut Vec<(diagnostic_code::DiagnosticFactTag, u64)>) {
201 facts.push((
202 diagnostic_code::DiagnosticFactTag::MutationOperation,
203 self.operation.raw(),
204 ));
205 if let Some(batch_position) = self.batch_position {
206 facts.push((
207 diagnostic_code::DiagnosticFactTag::BatchPosition,
208 u64::from(batch_position),
209 ));
210 }
211 }
212}
213
214pub struct DiagnosticFactDetail {
216 diagnostic: diagnostic_code::Diagnostic,
217 facts: Vec<(diagnostic_code::DiagnosticFactTag, u64)>,
218}
219
220pub struct InternalError {
228 pub(crate) class: ErrorClass,
229 pub(crate) origin: ErrorOrigin,
230
231 pub(crate) detail: Option<ErrorDetail>,
234}
235
236#[expect(
237 clippy::missing_const_for_fn,
238 reason = "internal error constructors stay non-const so compact diagnostic construction does not force const churn across subsystem helper seams"
239)]
240impl InternalError {
241 #[must_use]
245 #[cold]
246 #[inline(never)]
247 pub fn new(class: ErrorClass, origin: ErrorOrigin) -> Self {
248 let detail = match (class, origin) {
249 (ErrorClass::Corruption, ErrorOrigin::Store) => {
250 Some(ErrorDetail::Store(StoreError::Corrupt))
251 }
252 (ErrorClass::InvariantViolation, ErrorOrigin::Store) => {
253 Some(ErrorDetail::Store(StoreError::InvariantViolation))
254 }
255 _ => None,
256 };
257
258 Self {
259 class,
260 origin,
261 detail,
262 }
263 }
264
265 #[must_use]
267 pub const fn class(&self) -> ErrorClass {
268 self.class
269 }
270
271 #[must_use]
273 pub const fn origin(&self) -> ErrorOrigin {
274 self.origin
275 }
276
277 #[must_use]
279 pub const fn message(&self) -> &'static str {
280 compact_message_for(self.class, self.origin)
281 }
282
283 #[must_use]
285 pub const fn detail(&self) -> Option<&ErrorDetail> {
286 self.detail.as_ref()
287 }
288
289 #[must_use]
291 pub fn diagnostic(&self) -> diagnostic_code::Diagnostic {
292 diagnostic_code::Diagnostic::new(
293 self.diagnostic_code(),
294 self.origin.diagnostic_origin(),
295 self.detail
296 .as_ref()
297 .and_then(ErrorDetail::diagnostic_detail),
298 )
299 }
300
301 #[must_use]
303 #[cold]
304 #[inline(never)]
305 pub fn diagnostic_facts(&self) -> Vec<(diagnostic_code::DiagnosticFactTag, u64)> {
306 self.detail
307 .as_ref()
308 .map_or_else(Vec::new, ErrorDetail::diagnostic_facts)
309 }
310
311 #[must_use]
313 pub fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
314 self.detail.as_ref().map_or_else(
315 || self.class.diagnostic_code(self.origin),
316 ErrorDetail::diagnostic_code,
317 )
318 }
319
320 #[must_use]
322 pub fn into_message(self) -> String {
323 self.message().to_string()
324 }
325
326 #[cold]
328 #[inline(never)]
329 pub(crate) fn classified(class: ErrorClass, origin: ErrorOrigin) -> Self {
330 Self::new(class, origin)
331 }
332
333 #[cold]
334 #[inline(never)]
335 fn with_diagnostic_facts(
336 class: ErrorClass,
337 origin: ErrorOrigin,
338 detail: Option<diagnostic_code::DiagnosticDetail>,
339 facts: Vec<(diagnostic_code::DiagnosticFactTag, u64)>,
340 ) -> Self {
341 let code = match detail {
342 Some(detail) => detail.diagnostic_code(),
343 None => class.diagnostic_code(origin),
344 };
345 let diagnostic = diagnostic_code::Diagnostic::new(code, origin.diagnostic_origin(), detail);
346 if diagnostic_code::validate_known_diagnostic_fact_schema(
347 diagnostic.error_code(),
348 facts.as_slice(),
349 )
350 .is_err()
351 {
352 return Self::new(ErrorClass::InvariantViolation, origin);
353 }
354 Self {
355 class,
356 origin,
357 detail: Some(ErrorDetail::DiagnosticFacts(Box::new(
358 DiagnosticFactDetail { diagnostic, facts },
359 ))),
360 }
361 }
362
363 #[cold]
364 #[inline(never)]
365 fn mutation_boundary_with_facts(
366 class: ErrorClass,
367 boundary: diagnostic_code::RuntimeBoundaryCode,
368 facts: Vec<(diagnostic_code::DiagnosticFactTag, u64)>,
369 ) -> Self {
370 Self::with_diagnostic_facts(
371 class,
372 ErrorOrigin::Executor,
373 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary { boundary }),
374 facts,
375 )
376 }
377
378 #[cold]
379 #[inline(never)]
380 fn exact_key_batch_boundary_with_facts(
381 boundary: diagnostic_code::RuntimeBoundaryCode,
382 facts: Vec<(diagnostic_code::DiagnosticFactTag, u64)>,
383 ) -> Self {
384 Self::with_diagnostic_facts(
385 ErrorClass::Unsupported,
386 ErrorOrigin::Query,
387 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary { boundary }),
388 facts,
389 )
390 }
391
392 pub(crate) fn sql_query_entity_not_found() -> Self {
394 Self::with_diagnostic_facts(
395 ErrorClass::NotFound,
396 ErrorOrigin::Interface,
397 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
398 boundary: diagnostic_code::RuntimeBoundaryCode::SqlQueryEntityNotFound,
399 }),
400 Vec::new(),
401 )
402 }
403
404 #[cold]
406 #[inline(never)]
407 pub(crate) fn execution_budget_exceeded(
408 resource: diagnostic_code::DiagnosticExecutionBudgetResource,
409 limit: u64,
410 observed: u64,
411 scope: diagnostic_code::DiagnosticExecutionBudgetScope,
412 lane: diagnostic_code::DiagnosticExecutionLane,
413 normalized_shape_fingerprint_prefix: u64,
414 ) -> Self {
415 Self::with_diagnostic_facts(
416 ErrorClass::Unsupported,
417 ErrorOrigin::Executor,
418 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
419 boundary: diagnostic_code::RuntimeBoundaryCode::ExecutionBudgetExceeded,
420 }),
421 vec![
422 (
423 diagnostic_code::DiagnosticFactTag::BudgetResource,
424 resource.raw(),
425 ),
426 (diagnostic_code::DiagnosticFactTag::Limit, limit),
427 (diagnostic_code::DiagnosticFactTag::Actual, observed),
428 (
429 diagnostic_code::DiagnosticFactTag::ExecutionBudgetScope,
430 scope.raw(),
431 ),
432 (
433 diagnostic_code::DiagnosticFactTag::ExecutionLane,
434 lane.raw(),
435 ),
436 (
437 diagnostic_code::DiagnosticFactTag::QueryShapeFingerprintPrefix,
438 normalized_shape_fingerprint_prefix,
439 ),
440 ],
441 )
442 }
443
444 #[cold]
446 #[inline(never)]
447 pub(crate) fn relation_budget_exceeded(
448 resource: diagnostic_code::DiagnosticExecutionBudgetResource,
449 limit: u64,
450 observed: u64,
451 ) -> Self {
452 Self::execution_budget_exceeded(
453 resource,
454 limit,
455 observed,
456 diagnostic_code::DiagnosticExecutionBudgetScope::Execution,
457 diagnostic_code::DiagnosticExecutionLane::Mutation,
458 0,
459 )
460 }
461
462 #[cold]
464 #[inline(never)]
465 pub(crate) fn page_unit_too_large(
466 resource: diagnostic_code::DiagnosticExecutionBudgetResource,
467 limit: u64,
468 attempted: u64,
469 ) -> Self {
470 Self::with_diagnostic_facts(
471 ErrorClass::Unsupported,
472 ErrorOrigin::Executor,
473 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
474 boundary: diagnostic_code::RuntimeBoundaryCode::PageUnitTooLarge,
475 }),
476 vec![
477 (
478 diagnostic_code::DiagnosticFactTag::BudgetResource,
479 resource.raw(),
480 ),
481 (diagnostic_code::DiagnosticFactTag::Limit, limit),
482 (diagnostic_code::DiagnosticFactTag::Actual, attempted),
483 ],
484 )
485 }
486
487 #[cold]
492 #[inline(never)]
493 pub(crate) fn with_origin(self, origin: ErrorOrigin) -> Self {
494 match self.detail {
495 Some(ErrorDetail::DiagnosticFacts(detail)) => Self::with_diagnostic_facts(
496 self.class,
497 origin,
498 detail.diagnostic.detail().copied(),
499 detail.facts,
500 ),
501 _ => Self::classified(self.class, origin),
502 }
503 }
504
505 #[cold]
507 #[inline(never)]
508 pub(crate) fn index_invariant() -> Self {
509 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Index)
510 }
511
512 pub(crate) fn index_key_field_count_exceeds_max(
514 entity_tag: u64,
515 physical_generation: u64,
516 field_count: usize,
517 max_fields: usize,
518 ) -> Self {
519 Self::with_diagnostic_facts(
520 ErrorClass::InvariantViolation,
521 ErrorOrigin::Index,
522 None,
523 vec![
524 (diagnostic_code::DiagnosticFactTag::EntityTag, entity_tag),
525 (
526 diagnostic_code::DiagnosticFactTag::PhysicalGeneration,
527 physical_generation,
528 ),
529 (
530 diagnostic_code::DiagnosticFactTag::ComponentKind,
531 diagnostic_code::DiagnosticComponentKind::IndexKey.raw(),
532 ),
533 (
534 diagnostic_code::DiagnosticFactTag::ActualArity,
535 field_count as u64,
536 ),
537 (
538 diagnostic_code::DiagnosticFactTag::Maximum,
539 max_fields as u64,
540 ),
541 ],
542 )
543 }
544
545 pub(crate) fn index_expression_source_type_mismatch(
547 _index_name: &str,
548 _expression: impl Sized,
549 _expected: impl Sized,
550 _source_label: &str,
551 ) -> Self {
552 Self::index_invariant()
553 }
554
555 #[cold]
558 #[inline(never)]
559 pub(crate) fn planner_executor_invariant() -> Self {
560 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Planner)
561 }
562
563 #[cold]
566 #[inline(never)]
567 pub(crate) fn query_executor_invariant() -> Self {
568 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Query)
569 }
570
571 #[cold]
574 #[inline(never)]
575 pub(crate) fn cursor_executor_invariant() -> Self {
576 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Cursor)
577 }
578
579 #[cold]
581 #[inline(never)]
582 pub(crate) fn executor_invariant() -> Self {
583 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Executor)
584 }
585
586 #[cold]
588 #[inline(never)]
589 pub(crate) fn executor_internal() -> Self {
590 Self::new(ErrorClass::Internal, ErrorOrigin::Executor)
591 }
592
593 #[cold]
595 #[inline(never)]
596 pub(crate) fn executor_unsupported() -> Self {
597 Self::new(ErrorClass::Unsupported, ErrorOrigin::Executor)
598 }
599
600 #[cold]
602 #[inline(never)]
603 pub(crate) fn mutation_database_owned_field_explicit(
604 context: MutationDiagnosticContext,
605 field_id: u32,
606 ) -> Self {
607 Self::mutation_boundary_with_facts(
608 ErrorClass::Unsupported,
609 diagnostic_code::RuntimeBoundaryCode::MutationDatabaseOwnedFieldExplicit,
610 context.facts(Some(field_id)),
611 )
612 }
613
614 #[must_use]
616 #[cold]
617 #[inline(never)]
618 pub(crate) fn mutation_required_field_missing(
619 context: MutationDiagnosticContext,
620 field_id: u32,
621 ) -> Self {
622 Self::mutation_boundary_with_facts(
623 ErrorClass::Unsupported,
624 diagnostic_code::RuntimeBoundaryCode::MutationRequiredFieldMissing,
625 context.facts(Some(field_id)),
626 )
627 }
628
629 #[must_use]
631 #[cold]
632 #[inline(never)]
633 pub(crate) fn mutation_managed_timestamp_regression(
634 context: MutationDiagnosticContext,
635 ) -> Self {
636 Self::mutation_boundary_with_facts(
637 ErrorClass::InvariantViolation,
638 diagnostic_code::RuntimeBoundaryCode::MutationManagedTimestampRegression,
639 context.facts(None),
640 )
641 }
642
643 pub(crate) fn mutation_constraint_violation(context: AcceptedConstraintFactContext) -> Self {
645 Self::mutation_boundary_with_facts(
646 ErrorClass::InvariantViolation,
647 diagnostic_code::RuntimeBoundaryCode::ConstraintViolation,
648 context.facts(),
649 )
650 }
651
652 pub(crate) fn accepted_row_constraint_program_corrupt() -> Self {
654 Self {
655 class: ErrorClass::Corruption,
656 origin: ErrorOrigin::Executor,
657 detail: Some(ErrorDetail::Executor(
658 ExecutorErrorDetail::AcceptedRowConstraintProgramCorrupt,
659 )),
660 }
661 }
662
663 pub(crate) fn mutation_constraint_activation_write_blocked(
665 context: AcceptedConstraintFactContext,
666 ) -> Self {
667 Self::mutation_boundary_with_facts(
668 ErrorClass::Conflict,
669 diagnostic_code::RuntimeBoundaryCode::ConstraintActivationWriteBlocked,
670 context.facts(),
671 )
672 }
673
674 pub(crate) fn scalar_page_cursor_boundary_order_required() -> Self {
676 Self::query_executor_invariant()
677 }
678
679 pub(crate) fn scalar_page_cursor_boundary_after_ordering_required() -> Self {
681 Self::query_executor_invariant()
682 }
683
684 pub(crate) fn scalar_page_pagination_after_ordering_required() -> Self {
686 Self::query_executor_invariant()
687 }
688
689 pub(crate) fn fast_stream_route_kind_request_match_required() -> Self {
691 Self::query_executor_invariant()
692 }
693
694 pub(crate) fn secondary_index_prefix_spec_required() -> Self {
696 Self::query_executor_invariant()
697 }
698
699 pub(crate) fn index_range_limit_spec_required() -> Self {
701 Self::query_executor_invariant()
702 }
703
704 #[cold]
706 #[inline(never)]
707 pub(crate) fn mutation_atomic_save_duplicate_key(
708 entity_tag: u64,
709 first_position: u32,
710 duplicate_position: u32,
711 ) -> Self {
712 Self::mutation_boundary_with_facts(
713 ErrorClass::Conflict,
714 diagnostic_code::RuntimeBoundaryCode::MutationBatchDuplicateKey,
715 vec![
716 (diagnostic_code::DiagnosticFactTag::EntityTag, entity_tag),
717 (
718 diagnostic_code::DiagnosticFactTag::FirstBatchPosition,
719 u64::from(first_position),
720 ),
721 (
722 diagnostic_code::DiagnosticFactTag::DuplicateBatchPosition,
723 u64::from(duplicate_position),
724 ),
725 ],
726 )
727 }
728
729 #[cold]
731 #[inline(never)]
732 pub(crate) fn mutation_batch_empty() -> Self {
733 Self::mutation_boundary_with_facts(
734 ErrorClass::Unsupported,
735 diagnostic_code::RuntimeBoundaryCode::MutationBatchEmpty,
736 vec![(diagnostic_code::DiagnosticFactTag::ActualCount, 0)],
737 )
738 }
739
740 #[cold]
742 #[inline(never)]
743 pub(crate) fn mutation_batch_too_many_items(actual_count: usize, limit: usize) -> Self {
744 Self::mutation_boundary_with_facts(
745 ErrorClass::Unsupported,
746 diagnostic_code::RuntimeBoundaryCode::MutationBatchTooManyItems,
747 vec![
748 (
749 diagnostic_code::DiagnosticFactTag::ActualCount,
750 actual_count as u64,
751 ),
752 (diagnostic_code::DiagnosticFactTag::Limit, limit as u64),
753 ],
754 )
755 }
756
757 #[cold]
759 #[inline(never)]
760 pub(crate) fn mutation_batch_staged_bytes_exceeded(
761 actual_bytes: Option<usize>,
762 limit: usize,
763 ) -> Self {
764 let mut facts = Vec::with_capacity(1 + usize::from(actual_bytes.is_some()));
765 if let Some(actual_bytes) = actual_bytes {
766 facts.push((
767 diagnostic_code::DiagnosticFactTag::ActualLength,
768 actual_bytes as u64,
769 ));
770 }
771 facts.push((diagnostic_code::DiagnosticFactTag::Limit, limit as u64));
772 Self::mutation_boundary_with_facts(
773 ErrorClass::Unsupported,
774 diagnostic_code::RuntimeBoundaryCode::MutationBatchStagedBytesExceeded,
775 facts,
776 )
777 }
778
779 #[cold]
781 #[inline(never)]
782 pub(crate) fn mutation_batch_result_bytes_exceeded(actual_bytes: usize, limit: usize) -> Self {
783 Self::mutation_boundary_with_facts(
784 ErrorClass::Unsupported,
785 diagnostic_code::RuntimeBoundaryCode::MutationBatchResultBytesExceeded,
786 vec![
787 (
788 diagnostic_code::DiagnosticFactTag::ActualLength,
789 actual_bytes as u64,
790 ),
791 (diagnostic_code::DiagnosticFactTag::Limit, limit as u64),
792 ],
793 )
794 }
795
796 #[cold]
798 #[inline(never)]
799 pub(crate) fn mutation_batch_commit_work_exceeded(
800 actual_units: Option<usize>,
801 limit: usize,
802 ) -> Self {
803 let mut facts = Vec::with_capacity(1 + usize::from(actual_units.is_some()));
804 if let Some(actual_units) = actual_units {
805 facts.push((
806 diagnostic_code::DiagnosticFactTag::ActualCount,
807 actual_units as u64,
808 ));
809 }
810 facts.push((diagnostic_code::DiagnosticFactTag::Limit, limit as u64));
811 Self::mutation_boundary_with_facts(
812 ErrorClass::Unsupported,
813 diagnostic_code::RuntimeBoundaryCode::MutationBatchCommitWorkExceeded,
814 facts,
815 )
816 }
817
818 pub(crate) fn convergence_backlog_pressure(
820 resource: diagnostic_code::DiagnosticBacklogResource,
821 current: u64,
822 proposed: u64,
823 limit: u64,
824 ) -> Self {
825 Self::mutation_boundary_with_facts(
826 ErrorClass::Conflict,
827 diagnostic_code::RuntimeBoundaryCode::ConvergenceBacklogPressure,
828 vec![
829 (
830 diagnostic_code::DiagnosticFactTag::BacklogResource,
831 resource.raw(),
832 ),
833 (diagnostic_code::DiagnosticFactTag::CurrentCount, current),
834 (diagnostic_code::DiagnosticFactTag::ProposedCount, proposed),
835 (diagnostic_code::DiagnosticFactTag::Limit, limit),
836 ],
837 )
838 }
839
840 #[cold]
842 #[inline(never)]
843 pub(crate) fn exact_key_batch_too_many_items(actual_count: usize, limit: usize) -> Self {
844 Self::exact_key_batch_boundary_with_facts(
845 diagnostic_code::RuntimeBoundaryCode::ExactKeyBatchTooManyItems,
846 vec![
847 (
848 diagnostic_code::DiagnosticFactTag::ActualCount,
849 actual_count as u64,
850 ),
851 (diagnostic_code::DiagnosticFactTag::Limit, limit as u64),
852 ],
853 )
854 }
855
856 #[cold]
858 #[inline(never)]
859 pub(crate) fn exact_key_batch_input_bytes_exceeded(actual_bytes: usize, limit: usize) -> Self {
860 Self::exact_key_batch_bytes_exceeded(
861 diagnostic_code::RuntimeBoundaryCode::ExactKeyBatchInputBytesExceeded,
862 actual_bytes,
863 limit,
864 )
865 }
866
867 #[cold]
869 #[inline(never)]
870 pub(crate) fn exact_key_batch_stored_bytes_exceeded(actual_bytes: usize, limit: usize) -> Self {
871 Self::exact_key_batch_bytes_exceeded(
872 diagnostic_code::RuntimeBoundaryCode::ExactKeyBatchStoredBytesExceeded,
873 actual_bytes,
874 limit,
875 )
876 }
877
878 #[cold]
880 #[inline(never)]
881 pub(crate) fn exact_key_batch_result_bytes_exceeded(actual_bytes: usize, limit: usize) -> Self {
882 Self::exact_key_batch_bytes_exceeded(
883 diagnostic_code::RuntimeBoundaryCode::ExactKeyBatchResultBytesExceeded,
884 actual_bytes,
885 limit,
886 )
887 }
888
889 #[cold]
890 #[inline(never)]
891 fn exact_key_batch_bytes_exceeded(
892 boundary: diagnostic_code::RuntimeBoundaryCode,
893 actual_bytes: usize,
894 limit: usize,
895 ) -> Self {
896 Self::exact_key_batch_boundary_with_facts(
897 boundary,
898 vec![
899 (
900 diagnostic_code::DiagnosticFactTag::ActualLength,
901 actual_bytes as u64,
902 ),
903 (diagnostic_code::DiagnosticFactTag::Limit, limit as u64),
904 ],
905 )
906 }
907
908 #[cold]
910 #[inline(never)]
911 pub(crate) fn mutation_batch_store_mismatch(
912 batch_position: u32,
913 expected_entity_tag: u64,
914 actual_entity_tag: u64,
915 ) -> Self {
916 Self::mutation_boundary_with_facts(
917 ErrorClass::Conflict,
918 diagnostic_code::RuntimeBoundaryCode::MutationBatchStoreMismatch,
919 vec![
920 (
921 diagnostic_code::DiagnosticFactTag::BatchPosition,
922 u64::from(batch_position),
923 ),
924 (
925 diagnostic_code::DiagnosticFactTag::ExpectedEntityTag,
926 expected_entity_tag,
927 ),
928 (
929 diagnostic_code::DiagnosticFactTag::ActualEntityTag,
930 actual_entity_tag,
931 ),
932 ],
933 )
934 }
935
936 #[cold]
938 #[inline(never)]
939 pub(crate) fn mutation_batch_too_many_entities(actual_count: usize, limit: usize) -> Self {
940 Self::mutation_boundary_with_facts(
941 ErrorClass::Unsupported,
942 diagnostic_code::RuntimeBoundaryCode::MutationBatchTooManyEntities,
943 vec![
944 (
945 diagnostic_code::DiagnosticFactTag::ActualCount,
946 actual_count as u64,
947 ),
948 (diagnostic_code::DiagnosticFactTag::Limit, limit as u64),
949 ],
950 )
951 }
952
953 pub(crate) fn mutation_index_store_generation_changed(
955 _expected_generation: u64,
956 _observed_generation: u64,
957 ) -> Self {
958 Self::executor_invariant()
959 }
960
961 #[cold]
963 #[inline(never)]
964 pub(crate) fn planner_invariant() -> Self {
965 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Planner)
966 }
967
968 pub(crate) fn query_invalid_logical_plan() -> Self {
970 Self::planner_invariant()
971 }
972
973 pub(crate) fn store_invariant() -> Self {
975 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Store)
976 }
977
978 #[cold]
980 #[inline(never)]
981 pub(crate) fn store_internal() -> Self {
982 Self::new(ErrorClass::Internal, ErrorOrigin::Store)
983 }
984
985 pub(crate) fn commit_memory_id_unconfigured() -> Self {
987 Self::store_internal()
988 }
989
990 pub(crate) fn commit_store_uninitialized() -> Self {
992 Self::store_invariant()
993 }
994
995 pub(crate) fn commit_memory_id_mismatch(cached_id: u8, configured_id: u8) -> Self {
997 Self::with_diagnostic_facts(
998 ErrorClass::Internal,
999 ErrorOrigin::Store,
1000 None,
1001 vec![
1002 (
1003 diagnostic_code::DiagnosticFactTag::ExpectedMemoryId,
1004 u64::from(cached_id),
1005 ),
1006 (
1007 diagnostic_code::DiagnosticFactTag::ActualMemoryId,
1008 u64::from(configured_id),
1009 ),
1010 ],
1011 )
1012 }
1013
1014 pub(crate) fn commit_memory_stable_key_mismatch(
1016 _cached_key: &str,
1017 _configured_key: &str,
1018 ) -> Self {
1019 Self::store_internal()
1020 }
1021
1022 pub(crate) fn database_incarnation_generation_failed() -> Self {
1024 Self::store_internal()
1025 }
1026
1027 pub(crate) fn database_incarnation_invalid() -> Self {
1029 Self::store_corruption()
1030 }
1031
1032 pub(crate) fn recovery_unsupported_database_format(found: Option<u16>, required: u16) -> Self {
1034 Self {
1035 class: ErrorClass::IncompatiblePersistedFormat,
1036 origin: ErrorOrigin::Recovery,
1037 detail: Some(ErrorDetail::Recovery(
1038 RecoveryErrorDetail::UnsupportedFormatVersion { found, required },
1039 )),
1040 }
1041 }
1042
1043 pub(crate) fn recovery_malformed_database_format_marker(
1045 reason: RecoveryFormatMarkerError,
1046 ) -> Self {
1047 Self {
1048 class: ErrorClass::Corruption,
1049 origin: ErrorOrigin::Recovery,
1050 detail: Some(ErrorDetail::Recovery(
1051 RecoveryErrorDetail::MalformedFormatMarker { reason },
1052 )),
1053 }
1054 }
1055
1056 pub(crate) fn recovery_database_format_control_unavailable() -> Self {
1058 Self::new(ErrorClass::Internal, ErrorOrigin::Recovery)
1059 }
1060
1061 pub(crate) fn recovery_pending() -> Self {
1063 Self::with_diagnostic_facts(
1064 ErrorClass::Conflict,
1065 ErrorOrigin::Recovery,
1066 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
1067 boundary: diagnostic_code::RuntimeBoundaryCode::DatabaseStartupRecoveryPending,
1068 }),
1069 Vec::new(),
1070 )
1071 }
1072
1073 pub(crate) fn startup_control_corruption() -> Self {
1075 Self::new(ErrorClass::Corruption, ErrorOrigin::Recovery)
1076 }
1077
1078 pub(crate) fn commit_control_memory_growth_failed() -> Self {
1080 Self::store_internal()
1081 }
1082
1083 #[cfg(not(test))]
1085 pub(crate) fn database_format_memory_registration_failed(_err: impl Sized) -> Self {
1086 Self::store_internal()
1087 }
1088
1089 pub(crate) fn recovery_effect_verification_failed() -> Self {
1091 Self::store_corruption()
1092 }
1093
1094 #[cold]
1096 #[inline(never)]
1097 pub(crate) fn index_internal() -> Self {
1098 Self::new(ErrorClass::Internal, ErrorOrigin::Index)
1099 }
1100
1101 pub(crate) fn structural_index_removal_entity_key_required() -> Self {
1103 Self::index_internal()
1104 }
1105
1106 pub(crate) fn structural_index_insertion_entity_key_required() -> Self {
1108 Self::index_internal()
1109 }
1110
1111 pub(crate) fn index_commit_op_old_entity_key_required() -> Self {
1113 Self::index_internal()
1114 }
1115
1116 pub(crate) fn index_commit_op_new_entity_key_required() -> Self {
1118 Self::index_internal()
1119 }
1120
1121 #[cfg(test)]
1123 pub(crate) fn query_internal() -> Self {
1124 Self::new(ErrorClass::Internal, ErrorOrigin::Query)
1125 }
1126
1127 #[cold]
1129 #[inline(never)]
1130 pub(crate) fn query_unsupported() -> Self {
1131 Self::new(ErrorClass::Unsupported, ErrorOrigin::Query)
1132 }
1133
1134 #[cold]
1137 #[inline(never)]
1138 pub(crate) fn query_stale_accepted_schema_revision(
1139 expected_revision: u64,
1140 current_revision: Option<u64>,
1141 ) -> Self {
1142 let mut facts = Vec::with_capacity(1 + usize::from(current_revision.is_some()));
1143 facts.push((
1144 diagnostic_code::DiagnosticFactTag::ExpectedRevision,
1145 expected_revision,
1146 ));
1147 if let Some(current_revision) = current_revision {
1148 facts.push((
1149 diagnostic_code::DiagnosticFactTag::CurrentRevision,
1150 current_revision,
1151 ));
1152 }
1153 Self::with_diagnostic_facts(ErrorClass::Conflict, ErrorOrigin::Query, None, facts)
1154 }
1155
1156 #[cold]
1158 #[inline(never)]
1159 #[cfg(feature = "sql")]
1160 pub(crate) fn query_schema_ddl_admission(error: SchemaDdlAdmissionError) -> Self {
1161 Self {
1162 class: ErrorClass::Unsupported,
1163 origin: ErrorOrigin::Query,
1164 detail: Some(ErrorDetail::Query(QueryErrorDetail::SchemaDdlAdmission {
1165 error,
1166 })),
1167 }
1168 }
1169
1170 #[cold]
1172 #[inline(never)]
1173 pub(crate) fn query_numeric_overflow() -> Self {
1174 Self {
1175 class: ErrorClass::Unsupported,
1176 origin: ErrorOrigin::Query,
1177 detail: Some(ErrorDetail::Query(QueryErrorDetail::NumericOverflow)),
1178 }
1179 }
1180
1181 #[cold]
1184 #[inline(never)]
1185 pub(crate) fn query_numeric_not_representable() -> Self {
1186 Self {
1187 class: ErrorClass::Unsupported,
1188 origin: ErrorOrigin::Query,
1189 detail: Some(ErrorDetail::Query(
1190 QueryErrorDetail::NumericNotRepresentable,
1191 )),
1192 }
1193 }
1194
1195 #[cold]
1197 #[inline(never)]
1198 pub(crate) fn serialize_internal() -> Self {
1199 Self::new(ErrorClass::Internal, ErrorOrigin::Serialize)
1200 }
1201
1202 pub(crate) fn persisted_row_encode_failed(_detail: impl Sized) -> Self {
1204 Self::persisted_row_encode_internal()
1205 }
1206
1207 pub(crate) fn persisted_row_encode_internal() -> Self {
1209 Self::serialize_internal()
1210 }
1211
1212 pub(crate) fn persisted_row_field_encode_internal(_field_name: &str) -> Self {
1214 Self::persisted_row_encode_internal()
1215 }
1216
1217 #[cold]
1219 #[inline(never)]
1220 pub(crate) fn store_corruption() -> Self {
1221 Self::new(ErrorClass::Corruption, ErrorOrigin::Store)
1222 }
1223
1224 pub(crate) fn commit_corruption() -> Self {
1226 Self::store_corruption()
1227 }
1228
1229 pub(crate) fn commit_component_corruption() -> Self {
1231 Self::commit_corruption()
1232 }
1233
1234 pub(crate) fn commit_id_generation_failed() -> Self {
1236 Self::store_internal()
1237 }
1238
1239 pub(crate) fn commit_marker_payload_exceeds_u32_length_limit() -> Self {
1241 Self::store_unsupported()
1242 }
1243
1244 pub(crate) fn commit_component_length_invalid(actual_length: usize, limit: usize) -> Self {
1246 Self::with_diagnostic_facts(
1247 ErrorClass::Corruption,
1248 ErrorOrigin::Store,
1249 None,
1250 vec![
1251 (
1252 diagnostic_code::DiagnosticFactTag::ComponentKind,
1253 diagnostic_code::DiagnosticComponentKind::CommitDataKey.raw(),
1254 ),
1255 (
1256 diagnostic_code::DiagnosticFactTag::ActualLength,
1257 actual_length as u64,
1258 ),
1259 (diagnostic_code::DiagnosticFactTag::Limit, limit as u64),
1260 ],
1261 )
1262 }
1263
1264 pub(crate) fn commit_marker_exceeds_max_size() -> Self {
1266 Self::commit_corruption()
1267 }
1268
1269 pub(crate) fn commit_control_slot_exceeds_max_size() -> Self {
1271 Self::store_unsupported()
1272 }
1273
1274 pub(crate) fn commit_control_slot_marker_bytes_exceed_u32_length_limit() -> Self {
1276 Self::store_unsupported()
1277 }
1278
1279 #[cold]
1281 #[inline(never)]
1282 pub(crate) fn index_corruption() -> Self {
1283 Self::new(ErrorClass::Corruption, ErrorOrigin::Index)
1284 }
1285
1286 pub(crate) fn index_unique_validation_corruption() -> Self {
1288 Self::index_plan_index_corruption()
1289 }
1290
1291 pub(crate) fn structural_index_entry_corruption() -> Self {
1293 Self::index_plan_index_corruption()
1294 }
1295
1296 pub(crate) fn index_unique_validation_entity_key_required() -> Self {
1298 Self::index_invariant()
1299 }
1300
1301 pub(crate) fn index_unique_validation_row_deserialize_failed() -> Self {
1303 Self::index_plan_serialize_corruption()
1304 }
1305
1306 pub(crate) fn index_unique_validation_primary_key_decode_failed() -> Self {
1308 Self::index_plan_serialize_corruption()
1309 }
1310
1311 pub(crate) fn index_unique_validation_key_rebuild_failed() -> Self {
1313 Self::index_plan_serialize_corruption()
1314 }
1315
1316 pub(crate) fn index_unique_validation_row_required() -> Self {
1318 Self::index_plan_store_corruption()
1319 }
1320
1321 pub(crate) fn index_only_predicate_component_required() -> Self {
1323 Self::index_invariant()
1324 }
1325
1326 pub(crate) fn index_scan_continuation_anchor_within_envelope_required() -> Self {
1328 Self::index_invariant()
1329 }
1330
1331 pub(crate) fn index_scan_continuation_advancement_required() -> Self {
1333 Self::index_invariant()
1334 }
1335
1336 pub(crate) fn index_scan_key_corrupted_during(
1338 _context: &'static str,
1339 _err: impl Sized,
1340 ) -> Self {
1341 Self::index_corruption()
1342 }
1343
1344 pub(crate) fn index_projection_component_required(
1346 _index_name: &str,
1347 _component_index: usize,
1348 ) -> Self {
1349 Self::index_invariant()
1350 }
1351
1352 pub(crate) fn index_entry_decode_failed() -> Self {
1354 Self::index_corruption()
1355 }
1356
1357 pub(crate) fn serialize_corruption() -> Self {
1359 Self::new(ErrorClass::Corruption, ErrorOrigin::Serialize)
1360 }
1361
1362 pub(crate) fn persisted_row_decode_corruption() -> Self {
1364 Self::serialize_corruption()
1365 }
1366
1367 pub(crate) fn persisted_row_layout_outside_accepted_window(
1369 row_layout: u32,
1370 history_floor: u32,
1371 current_layout: u32,
1372 ) -> Self {
1373 Self::with_diagnostic_facts(
1374 ErrorClass::Corruption,
1375 ErrorOrigin::Serialize,
1376 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
1377 boundary:
1378 diagnostic_code::RuntimeBoundaryCode::PersistedRowLayoutOutsideAcceptedWindow,
1379 }),
1380 vec![
1381 (
1382 diagnostic_code::DiagnosticFactTag::RowLayout,
1383 u64::from(row_layout),
1384 ),
1385 (
1386 diagnostic_code::DiagnosticFactTag::HistoryFloor,
1387 u64::from(history_floor),
1388 ),
1389 (
1390 diagnostic_code::DiagnosticFactTag::CurrentLayout,
1391 u64::from(current_layout),
1392 ),
1393 ],
1394 )
1395 }
1396
1397 pub(crate) fn persisted_row_slot_count_mismatch(
1399 row_layout: u32,
1400 expected_slot_count: usize,
1401 actual_slot_count: usize,
1402 ) -> Self {
1403 Self::with_diagnostic_facts(
1404 ErrorClass::Corruption,
1405 ErrorOrigin::Serialize,
1406 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
1407 boundary: diagnostic_code::RuntimeBoundaryCode::PersistedRowSlotCountMismatch,
1408 }),
1409 vec![
1410 (
1411 diagnostic_code::DiagnosticFactTag::RowLayout,
1412 u64::from(row_layout),
1413 ),
1414 (
1415 diagnostic_code::DiagnosticFactTag::ExpectedSlotCount,
1416 expected_slot_count as u64,
1417 ),
1418 (
1419 diagnostic_code::DiagnosticFactTag::ActualSlotCount,
1420 actual_slot_count as u64,
1421 ),
1422 ],
1423 )
1424 }
1425
1426 pub(crate) fn persisted_row_field_decode_failed(field_name: &str, _detail: impl Sized) -> Self {
1428 Self::persisted_row_field_decode_corruption(field_name)
1429 }
1430
1431 pub(crate) fn persisted_row_field_decode_corruption(_field_name: &str) -> Self {
1433 Self::persisted_row_decode_corruption()
1434 }
1435
1436 pub(crate) fn persisted_row_field_kind_decode_failed(
1438 field_name: &str,
1439 _field_kind: impl fmt::Debug,
1440 _detail: impl Sized,
1441 ) -> Self {
1442 Self::persisted_row_field_decode_corruption(field_name)
1443 }
1444
1445 pub(crate) fn persisted_row_field_payload_exact_len_required(field_name: &str) -> Self {
1447 Self::persisted_row_field_decode_corruption(field_name)
1448 }
1449
1450 pub(crate) fn persisted_row_field_payload_must_be_empty(field_name: &str) -> Self {
1452 Self::persisted_row_field_decode_corruption(field_name)
1453 }
1454
1455 pub(crate) fn persisted_row_field_payload_invalid_byte(field_name: &str) -> Self {
1457 Self::persisted_row_field_decode_corruption(field_name)
1458 }
1459
1460 pub(crate) fn persisted_row_field_payload_non_finite(field_name: &str) -> Self {
1462 Self::persisted_row_field_decode_corruption(field_name)
1463 }
1464
1465 pub(crate) fn persisted_row_field_text_payload_invalid_utf8(field_name: &str) -> Self {
1467 Self::persisted_row_field_decode_corruption(field_name)
1468 }
1469
1470 pub(crate) fn persisted_row_slot_lookup_out_of_bounds(_model_path: &str, _slot: usize) -> Self {
1472 Self::index_invariant()
1473 }
1474
1475 pub(crate) fn persisted_row_slot_cache_lookup_out_of_bounds(
1477 _model_path: &str,
1478 _slot: usize,
1479 ) -> Self {
1480 Self::index_invariant()
1481 }
1482
1483 pub(crate) fn persisted_row_primary_key_not_primary_key_encodable(
1485 _data_key: impl fmt::Debug,
1486 _detail: impl Sized,
1487 ) -> Self {
1488 Self::persisted_row_decode_corruption()
1489 }
1490
1491 pub(crate) fn persisted_row_primary_key_slot_missing(_data_key: impl fmt::Debug) -> Self {
1493 Self::persisted_row_decode_corruption()
1494 }
1495
1496 pub(crate) fn persisted_row_key_mismatch() -> Self {
1498 Self::store_corruption()
1499 }
1500
1501 pub(crate) fn persisted_row_declared_field_missing(field_name: &str) -> Self {
1503 Self::persisted_row_field_decode_corruption(field_name)
1504 }
1505
1506 pub(crate) fn reverse_index_entry_corrupted(
1508 _source_path: &str,
1509 _field_name: &str,
1510 _target_path: &str,
1511 _index_key: impl fmt::Debug,
1512 _detail: impl Sized,
1513 ) -> Self {
1514 Self::index_corruption()
1515 }
1516
1517 pub(crate) fn relation_target_store_missing(
1519 _source_path: &str,
1520 _field_name: &str,
1521 _target_path: &str,
1522 _store_path: &str,
1523 _detail: impl Sized,
1524 ) -> Self {
1525 Self::executor_internal()
1526 }
1527
1528 pub(crate) fn relation_target_primary_key_arity_mismatch(
1530 expected_arity: usize,
1531 actual_arity: usize,
1532 ) -> Self {
1533 Self::with_diagnostic_facts(
1534 ErrorClass::Internal,
1535 ErrorOrigin::Executor,
1536 None,
1537 vec![
1538 (
1539 diagnostic_code::DiagnosticFactTag::ComponentKind,
1540 diagnostic_code::DiagnosticComponentKind::RelationTargetPrimaryKey.raw(),
1541 ),
1542 (
1543 diagnostic_code::DiagnosticFactTag::ExpectedArity,
1544 expected_arity as u64,
1545 ),
1546 (
1547 diagnostic_code::DiagnosticFactTag::ActualArity,
1548 actual_arity as u64,
1549 ),
1550 ],
1551 )
1552 }
1553
1554 pub(crate) fn relation_target_key_decode_failed(
1556 _context_label: &str,
1557 _source_path: &str,
1558 _field_name: &str,
1559 _target_path: &str,
1560 _detail: impl Sized,
1561 ) -> Self {
1562 Self::identity_corruption()
1563 }
1564
1565 pub(crate) fn relation_target_entity_mismatch(
1567 _context_label: &str,
1568 _source_path: &str,
1569 _field_name: &str,
1570 _target_path: &str,
1571 _target_entity_name: &str,
1572 expected_tag: u64,
1573 actual_tag: u64,
1574 ) -> Self {
1575 Self::with_diagnostic_facts(
1576 ErrorClass::Corruption,
1577 ErrorOrigin::Store,
1578 None,
1579 vec![
1580 (
1581 diagnostic_code::DiagnosticFactTag::ExpectedEntityTag,
1582 expected_tag,
1583 ),
1584 (
1585 diagnostic_code::DiagnosticFactTag::ActualEntityTag,
1586 actual_tag,
1587 ),
1588 ],
1589 )
1590 }
1591
1592 pub(crate) fn relation_source_row_decode_failed(
1594 _source_path: &str,
1595 _field_name: &str,
1596 _target_path: &str,
1597 _detail: impl Sized,
1598 ) -> Self {
1599 Self::persisted_row_decode_corruption()
1600 }
1601
1602 pub(crate) fn relation_source_row_unsupported_scalar_relation_key(
1604 _source_path: &str,
1605 _field_name: &str,
1606 _target_path: &str,
1607 ) -> Self {
1608 Self::persisted_row_decode_corruption()
1609 }
1610
1611 pub(crate) fn relation_source_row_unsupported_key_kind(_field_kind: impl fmt::Debug) -> Self {
1613 Self::persisted_row_decode_corruption()
1614 }
1615
1616 pub(crate) fn bytes_covering_component_payload_empty() -> Self {
1618 Self::index_corruption()
1619 }
1620
1621 pub(crate) fn bytes_covering_bool_payload_truncated() -> Self {
1623 Self::index_corruption()
1624 }
1625
1626 pub(crate) fn bytes_covering_component_payload_invalid_length() -> Self {
1628 Self::index_corruption()
1629 }
1630
1631 pub(crate) fn bytes_covering_bool_payload_invalid_value() -> Self {
1633 Self::index_corruption()
1634 }
1635
1636 pub(crate) fn bytes_covering_text_payload_invalid_terminator() -> Self {
1638 Self::index_corruption()
1639 }
1640
1641 pub(crate) fn bytes_covering_text_payload_trailing_bytes() -> Self {
1643 Self::index_corruption()
1644 }
1645
1646 pub(crate) fn bytes_covering_text_payload_invalid_utf8() -> Self {
1648 Self::index_corruption()
1649 }
1650
1651 pub(crate) fn bytes_covering_text_payload_invalid_escape_byte() -> Self {
1653 Self::index_corruption()
1654 }
1655
1656 pub(crate) fn bytes_covering_text_payload_missing_terminator() -> Self {
1658 Self::index_corruption()
1659 }
1660
1661 pub(crate) fn identity_corruption() -> Self {
1663 Self::new(ErrorClass::Corruption, ErrorOrigin::Identity)
1664 }
1665
1666 pub(crate) fn identity_state_corruption() -> Self {
1668 Self::identity_corruption()
1669 }
1670
1671 pub(crate) fn identity_state_conflict() -> Self {
1673 Self::new(ErrorClass::Conflict, ErrorOrigin::Identity)
1674 }
1675
1676 pub(crate) fn identity_state_capacity_exhausted() -> Self {
1678 Self::new(ErrorClass::Unsupported, ErrorOrigin::Identity)
1679 }
1680
1681 pub(crate) fn identity_exhausted() -> Self {
1683 Self::new(ErrorClass::Unsupported, ErrorOrigin::Identity)
1684 }
1685
1686 pub(crate) fn identity_candidate_count_exhausted() -> Self {
1688 Self::new(ErrorClass::Unsupported, ErrorOrigin::Identity)
1689 }
1690
1691 #[cold]
1693 #[inline(never)]
1694 pub(crate) fn store_unsupported() -> Self {
1695 Self::new(ErrorClass::Unsupported, ErrorOrigin::Store)
1696 }
1697
1698 pub(crate) fn schema_application_conflict() -> Self {
1700 Self::new(ErrorClass::Conflict, ErrorOrigin::Store)
1701 }
1702
1703 pub(crate) fn schema_migration(reason: diagnostic_code::SchemaMigrationCode) -> Self {
1705 let class = match reason.diagnostic_code() {
1706 diagnostic_code::DiagnosticCode::RuntimeConflict => ErrorClass::Conflict,
1707 diagnostic_code::DiagnosticCode::RuntimeCorruption => ErrorClass::Corruption,
1708 diagnostic_code::DiagnosticCode::RuntimeUnsupported => ErrorClass::Unsupported,
1709 _ => ErrorClass::Internal,
1710 };
1711 Self {
1712 class,
1713 origin: ErrorOrigin::Store,
1714 detail: Some(ErrorDetail::Store(StoreError::SchemaMigration { reason })),
1715 }
1716 }
1717
1718 pub(crate) fn schema_ddl_publication_race_lost(_entity_path: &str) -> Self {
1720 Self {
1721 class: ErrorClass::Unsupported,
1722 origin: ErrorOrigin::Store,
1723 detail: Some(ErrorDetail::Store(StoreError::SchemaDdlPublicationRaceLost)),
1724 }
1725 }
1726
1727 #[cfg(feature = "sql")]
1729 pub(crate) fn schema_ddl_rewrite_requires_migration(_entity_path: &str) -> Self {
1730 Self {
1731 class: ErrorClass::Unsupported,
1732 origin: ErrorOrigin::Store,
1733 detail: Some(ErrorDetail::Store(
1734 StoreError::SchemaDdlRewriteRequiresMigration,
1735 )),
1736 }
1737 }
1738
1739 pub(crate) fn journal_mutation_revision_exhausted() -> Self {
1741 Self {
1742 class: ErrorClass::Unsupported,
1743 origin: ErrorOrigin::Store,
1744 detail: Some(ErrorDetail::Store(
1745 StoreError::JournalMutationRevisionExhausted,
1746 )),
1747 }
1748 }
1749
1750 pub(crate) fn schema_transition_budget_exceeded(
1752 resource: SchemaTransitionBudgetResource,
1753 ) -> Self {
1754 Self {
1755 class: ErrorClass::Unsupported,
1756 origin: ErrorOrigin::Store,
1757 detail: Some(ErrorDetail::Store(
1758 StoreError::SchemaTransitionBudgetExceeded { resource },
1759 )),
1760 }
1761 }
1762
1763 pub(crate) fn unsupported_entity_tag_in_data_store(
1765 _entity_tag: crate::types::EntityTag,
1766 ) -> Self {
1767 Self::store_unsupported()
1768 }
1769
1770 #[cfg(not(test))]
1772 pub(crate) fn commit_memory_id_registration_failed(_err: impl Sized) -> Self {
1773 Self::store_internal()
1774 }
1775
1776 pub(crate) fn index_unsupported() -> Self {
1778 Self::new(ErrorClass::Unsupported, ErrorOrigin::Index)
1779 }
1780
1781 pub(crate) fn index_component_exceeds_max_size_at(
1783 entity_tag: u64,
1784 physical_generation: u64,
1785 component_index: usize,
1786 actual_length: usize,
1787 limit: usize,
1788 ) -> Self {
1789 Self::with_diagnostic_facts(
1790 ErrorClass::Unsupported,
1791 ErrorOrigin::Index,
1792 None,
1793 vec![
1794 (diagnostic_code::DiagnosticFactTag::EntityTag, entity_tag),
1795 (
1796 diagnostic_code::DiagnosticFactTag::PhysicalGeneration,
1797 physical_generation,
1798 ),
1799 (
1800 diagnostic_code::DiagnosticFactTag::ComponentIndex,
1801 component_index as u64,
1802 ),
1803 (
1804 diagnostic_code::DiagnosticFactTag::ComponentKind,
1805 diagnostic_code::DiagnosticComponentKind::IndexKeyComponent.raw(),
1806 ),
1807 (
1808 diagnostic_code::DiagnosticFactTag::ActualLength,
1809 actual_length as u64,
1810 ),
1811 (diagnostic_code::DiagnosticFactTag::Limit, limit as u64),
1812 ],
1813 )
1814 }
1815
1816 pub(crate) fn index_component_exceeds_max_size() -> Self {
1819 Self::index_unsupported()
1820 }
1821
1822 pub(crate) fn serialize_unsupported() -> Self {
1824 Self::new(ErrorClass::Unsupported, ErrorOrigin::Serialize)
1825 }
1826
1827 pub(crate) fn cursor_invalid_continuation() -> Self {
1829 Self::new(ErrorClass::Unsupported, ErrorOrigin::Cursor)
1830 }
1831
1832 pub(crate) fn serialize_incompatible_persisted_format() -> Self {
1834 Self::new(
1835 ErrorClass::IncompatiblePersistedFormat,
1836 ErrorOrigin::Serialize,
1837 )
1838 }
1839
1840 #[cfg(feature = "sql")]
1843 pub(crate) fn query_unsupported_sql_feature(feature: diagnostic_code::SqlFeatureCode) -> Self {
1844 Self {
1845 class: ErrorClass::Unsupported,
1846 origin: ErrorOrigin::Query,
1847 detail: Some(ErrorDetail::Query(
1848 QueryErrorDetail::UnsupportedSqlFeature { feature },
1849 )),
1850 }
1851 }
1852
1853 #[cfg(feature = "sql")]
1856 pub(crate) fn query_sql_lowering(reason: diagnostic_code::SqlLoweringCode) -> Self {
1857 Self {
1858 class: ErrorClass::Unsupported,
1859 origin: ErrorOrigin::Query,
1860 detail: Some(ErrorDetail::Query(QueryErrorDetail::SqlLowering { reason })),
1861 }
1862 }
1863
1864 #[cfg(feature = "sql")]
1866 pub(crate) fn query_sql_lowering_with_facts(
1867 reason: diagnostic_code::SqlLoweringCode,
1868 facts: Vec<(diagnostic_code::DiagnosticFactTag, u64)>,
1869 ) -> Self {
1870 Self::with_diagnostic_facts(
1871 ErrorClass::Unsupported,
1872 ErrorOrigin::Query,
1873 Some(diagnostic_code::DiagnosticDetail::SqlLowering { reason }),
1874 facts,
1875 )
1876 }
1877
1878 pub(crate) fn query_unsupported_projection(
1881 reason: diagnostic_code::QueryProjectionCode,
1882 ) -> Self {
1883 Self {
1884 class: ErrorClass::Unsupported,
1885 origin: ErrorOrigin::Query,
1886 detail: Some(ErrorDetail::Query(
1887 QueryErrorDetail::UnsupportedProjection { reason },
1888 )),
1889 }
1890 }
1891
1892 #[cfg(feature = "sql")]
1895 pub(crate) fn query_sql_surface_mismatch(
1896 mismatch: diagnostic_code::SqlSurfaceMismatchCode,
1897 ) -> Self {
1898 Self {
1899 class: ErrorClass::Unsupported,
1900 origin: ErrorOrigin::Query,
1901 detail: Some(ErrorDetail::Query(QueryErrorDetail::SqlSurfaceMismatch {
1902 mismatch,
1903 })),
1904 }
1905 }
1906
1907 pub(crate) fn query_sql_write_boundary(
1909 boundary: diagnostic_code::SqlWriteBoundaryCode,
1910 ) -> Self {
1911 Self {
1912 class: ErrorClass::Unsupported,
1913 origin: ErrorOrigin::Query,
1914 detail: Some(ErrorDetail::Query(QueryErrorDetail::SqlWriteBoundary {
1915 boundary,
1916 })),
1917 }
1918 }
1919
1920 pub(crate) fn query_sql_write_boundary_with_facts(
1922 boundary: diagnostic_code::SqlWriteBoundaryCode,
1923 facts: Vec<(diagnostic_code::DiagnosticFactTag, u64)>,
1924 ) -> Self {
1925 Self::with_diagnostic_facts(
1926 ErrorClass::Unsupported,
1927 ErrorOrigin::Query,
1928 Some(diagnostic_code::DiagnosticDetail::SqlWriteBoundary { boundary }),
1929 facts,
1930 )
1931 }
1932
1933 pub fn store_not_found(_key: impl Sized) -> Self {
1934 Self {
1935 class: ErrorClass::NotFound,
1936 origin: ErrorOrigin::Store,
1937 detail: Some(ErrorDetail::Store(StoreError::NotFound)),
1938 }
1939 }
1940
1941 pub fn unsupported_entity_path(_path: impl Sized) -> Self {
1943 Self::store_unsupported()
1944 }
1945
1946 #[cold]
1948 #[inline(never)]
1949 pub(crate) fn index_plan_corruption(origin: ErrorOrigin) -> Self {
1950 Self::new(ErrorClass::Corruption, origin)
1951 }
1952
1953 #[cold]
1955 #[inline(never)]
1956 pub(crate) fn index_plan_index_corruption() -> Self {
1957 Self::index_plan_corruption(ErrorOrigin::Index)
1958 }
1959
1960 #[cold]
1962 #[inline(never)]
1963 pub(crate) fn index_plan_store_corruption() -> Self {
1964 Self::index_plan_corruption(ErrorOrigin::Store)
1965 }
1966
1967 #[cold]
1969 #[inline(never)]
1970 pub(crate) fn index_plan_serialize_corruption() -> Self {
1971 Self::index_plan_corruption(ErrorOrigin::Serialize)
1972 }
1973
1974 #[cfg(test)]
1976 pub(crate) fn index_plan_invariant(origin: ErrorOrigin) -> Self {
1977 Self::new(ErrorClass::InvariantViolation, origin)
1978 }
1979
1980 #[cfg(test)]
1982 pub(crate) fn index_plan_store_invariant() -> Self {
1983 Self::index_plan_invariant(ErrorOrigin::Store)
1984 }
1985
1986 pub(crate) fn index_conflict() -> Self {
1992 Self::new(ErrorClass::Conflict, ErrorOrigin::Index)
1993 }
1994}
1995
1996impl From<diagnostic_code::QueryReadAdmissionCode> for InternalError {
1997 fn from(reason: diagnostic_code::QueryReadAdmissionCode) -> Self {
1998 Self {
1999 class: ErrorClass::Unsupported,
2000 origin: ErrorOrigin::Query,
2001 detail: Some(ErrorDetail::Query(QueryErrorDetail::QueryReadAdmission {
2002 reason,
2003 })),
2004 }
2005 }
2006}
2007
2008impl fmt::Debug for InternalError {
2009 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2010 fmt_compact_diagnostic(
2011 f,
2012 self.diagnostic_code(),
2013 self.detail
2014 .as_ref()
2015 .and_then(ErrorDetail::diagnostic_detail),
2016 )
2017 }
2018}
2019
2020impl fmt::Display for InternalError {
2021 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2022 f.write_str(self.message())
2023 }
2024}
2025
2026impl std::error::Error for InternalError {}
2027
2028#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq)]
2037pub enum ConstraintValuePathComponent {
2038 RootField { field_id: u32 },
2040
2041 RecordMember {
2043 composite_type_id: u32,
2044 member_id: u32,
2045 },
2046
2047 TupleElement {
2049 composite_type_id: u32,
2050 ordinal: u32,
2051 },
2052
2053 Newtype { composite_type_id: u32 },
2055
2056 EnumVariant { enum_type_id: u32, variant_id: u32 },
2058
2059 ListElement { index: u32 },
2061
2062 SetElement { index: u32 },
2064
2065 MapEntryKey { index: u32 },
2067
2068 MapEntryValue { index: u32 },
2070}
2071
2072impl fmt::Display for ConstraintValuePathComponent {
2073 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2074 match self {
2075 Self::RootField { field_id } => write!(f, "field#{field_id}"),
2076 Self::RecordMember {
2077 composite_type_id,
2078 member_id,
2079 } => write!(f, "record#{composite_type_id}.member#{member_id}"),
2080 Self::TupleElement {
2081 composite_type_id,
2082 ordinal,
2083 } => write!(f, "tuple#{composite_type_id}[{ordinal}]"),
2084 Self::Newtype { composite_type_id } => write!(f, "newtype#{composite_type_id}"),
2085 Self::EnumVariant {
2086 enum_type_id,
2087 variant_id,
2088 } => write!(f, "enum#{enum_type_id}.variant#{variant_id}"),
2089 Self::ListElement { index } => write!(f, "list[{index}]"),
2090 Self::SetElement { index } => write!(f, "set[{index}]"),
2091 Self::MapEntryKey { index } => write!(f, "map[{index}].key"),
2092 Self::MapEntryValue { index } => write!(f, "map[{index}].value"),
2093 }
2094 }
2095}
2096
2097#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
2104pub struct ConstraintValuePath {
2105 components: Vec<ConstraintValuePathComponent>,
2106}
2107
2108impl ConstraintValuePath {
2109 #[must_use]
2111 pub(crate) const fn new(components: Vec<ConstraintValuePathComponent>) -> Self {
2112 Self { components }
2113 }
2114
2115 #[must_use]
2117 pub const fn components(&self) -> &[ConstraintValuePathComponent] {
2118 self.components.as_slice()
2119 }
2120}
2121
2122impl fmt::Display for ConstraintValuePath {
2123 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2124 for (ordinal, component) in self.components.iter().enumerate() {
2125 if ordinal != 0 {
2126 f.write_str("/")?;
2127 }
2128 component.fmt(f)?;
2129 }
2130 Ok(())
2131 }
2132}
2133
2134#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
2143pub struct ConstraintValidationFindingOutput {
2144 accepted_schema_fingerprint: [u8; 16],
2145 entity_tag: u64,
2146 constraint_id: u32,
2147 primary_key: Vec<u8>,
2148 field_ids: Vec<u32>,
2149 value_path: Option<ConstraintValuePath>,
2150 error_code: u16,
2151}
2152
2153impl ConstraintValidationFindingOutput {
2154 #[must_use]
2156 pub(crate) const fn new(
2157 accepted_schema_fingerprint: [u8; 16],
2158 entity_tag: u64,
2159 constraint_id: u32,
2160 primary_key: Vec<u8>,
2161 field_ids: Vec<u32>,
2162 value_path: Option<ConstraintValuePath>,
2163 error_code: u16,
2164 ) -> Self {
2165 Self {
2166 accepted_schema_fingerprint,
2167 entity_tag,
2168 constraint_id,
2169 primary_key,
2170 field_ids,
2171 value_path,
2172 error_code,
2173 }
2174 }
2175
2176 #[must_use]
2178 pub const fn accepted_schema_fingerprint(&self) -> [u8; 16] {
2179 self.accepted_schema_fingerprint
2180 }
2181
2182 #[must_use]
2184 pub const fn entity_tag(&self) -> u64 {
2185 self.entity_tag
2186 }
2187
2188 #[must_use]
2190 pub const fn constraint_id(&self) -> u32 {
2191 self.constraint_id
2192 }
2193
2194 #[must_use]
2196 pub const fn primary_key(&self) -> &[u8] {
2197 self.primary_key.as_slice()
2198 }
2199
2200 #[must_use]
2202 pub const fn field_ids(&self) -> &[u32] {
2203 self.field_ids.as_slice()
2204 }
2205
2206 #[must_use]
2208 pub const fn value_path(&self) -> Option<&ConstraintValuePath> {
2209 self.value_path.as_ref()
2210 }
2211
2212 #[must_use]
2214 pub const fn error_code(&self) -> diagnostic_code::ErrorCode {
2215 diagnostic_code::ErrorCode::from_raw(self.error_code)
2216 }
2217
2218 #[must_use]
2220 pub const fn error_class(&self) -> diagnostic_code::ErrorClass {
2221 self.error_code().class()
2222 }
2223}
2224
2225#[derive(Clone)]
2227pub(crate) struct AcceptedConstraintFactContext {
2228 fingerprint_method: u8,
2229 accepted_schema_fingerprint: [u8; 16],
2230 entity_tag: u64,
2231 constraint_id: u32,
2232 constraint_kind: diagnostic_code::DiagnosticConstraintKind,
2233 mutation: Option<MutationDiagnosticContext>,
2234 value_path: Option<ConstraintValuePath>,
2235}
2236
2237impl AcceptedConstraintFactContext {
2238 #[must_use]
2239 pub(crate) fn write_admission(
2240 fingerprint_method: u8,
2241 accepted_schema_fingerprint: [u8; 16],
2242 entity_tag: u64,
2243 constraint_id: u32,
2244 constraint_kind: diagnostic_code::DiagnosticConstraintKind,
2245 mutation: Option<MutationDiagnosticContext>,
2246 value_path: Option<ConstraintValuePath>,
2247 ) -> Self {
2248 debug_assert!(mutation.is_none_or(|context| context.entity_tag() == entity_tag));
2249 Self {
2250 fingerprint_method,
2251 accepted_schema_fingerprint,
2252 entity_tag,
2253 constraint_id,
2254 constraint_kind,
2255 mutation,
2256 value_path,
2257 }
2258 }
2259
2260 fn facts(self) -> Vec<(diagnostic_code::DiagnosticFactTag, u64)> {
2261 let high = u64::from_be_bytes([
2262 self.accepted_schema_fingerprint[0],
2263 self.accepted_schema_fingerprint[1],
2264 self.accepted_schema_fingerprint[2],
2265 self.accepted_schema_fingerprint[3],
2266 self.accepted_schema_fingerprint[4],
2267 self.accepted_schema_fingerprint[5],
2268 self.accepted_schema_fingerprint[6],
2269 self.accepted_schema_fingerprint[7],
2270 ]);
2271 let low = u64::from_be_bytes([
2272 self.accepted_schema_fingerprint[8],
2273 self.accepted_schema_fingerprint[9],
2274 self.accepted_schema_fingerprint[10],
2275 self.accepted_schema_fingerprint[11],
2276 self.accepted_schema_fingerprint[12],
2277 self.accepted_schema_fingerprint[13],
2278 self.accepted_schema_fingerprint[14],
2279 self.accepted_schema_fingerprint[15],
2280 ]);
2281 let path_len = self
2282 .value_path
2283 .as_ref()
2284 .map_or(0, |path| path.components().len());
2285 let mutation_fact_count = self.mutation.map_or(0, |mutation| {
2286 1 + usize::from(mutation.batch_position.is_some())
2287 });
2288 let mut facts = Vec::with_capacity(7 + mutation_fact_count + path_len);
2289 facts.push((
2290 diagnostic_code::DiagnosticFactTag::AcceptedSchemaFingerprintMethod,
2291 u64::from(self.fingerprint_method),
2292 ));
2293 facts.push((
2294 diagnostic_code::DiagnosticFactTag::AcceptedSchemaFingerprintHigh,
2295 high,
2296 ));
2297 facts.push((
2298 diagnostic_code::DiagnosticFactTag::AcceptedSchemaFingerprintLow,
2299 low,
2300 ));
2301 facts.push((
2302 diagnostic_code::DiagnosticFactTag::EntityTag,
2303 self.entity_tag,
2304 ));
2305 facts.push((
2306 diagnostic_code::DiagnosticFactTag::ConstraintId,
2307 u64::from(self.constraint_id),
2308 ));
2309 facts.push((
2310 diagnostic_code::DiagnosticFactTag::ConstraintKind,
2311 self.constraint_kind.raw(),
2312 ));
2313 facts.push((
2314 diagnostic_code::DiagnosticFactTag::ConstraintContext,
2315 diagnostic_code::DiagnosticConstraintContext::WriteAdmission.raw(),
2316 ));
2317 if let Some(mutation) = self.mutation {
2318 mutation.append_operation_facts(&mut facts);
2319 }
2320 if let Some(path) = self.value_path {
2321 for component in path.components {
2322 facts.push(constraint_value_path_fact(component));
2323 }
2324 }
2325 debug_assert!(facts.len() <= diagnostic_code::MAX_PUBLIC_DIAGNOSTIC_FACTS);
2326 facts
2327 }
2328}
2329
2330fn constraint_value_path_fact(
2331 component: ConstraintValuePathComponent,
2332) -> (diagnostic_code::DiagnosticFactTag, u64) {
2333 use diagnostic_code::DiagnosticFactTag;
2334 match component {
2335 ConstraintValuePathComponent::RootField { field_id } => {
2336 (DiagnosticFactTag::RootField, u64::from(field_id))
2337 }
2338 ConstraintValuePathComponent::RecordMember {
2339 composite_type_id,
2340 member_id,
2341 } => (
2342 DiagnosticFactTag::RecordMember,
2343 diagnostic_code::pack_u32_pair(composite_type_id, member_id),
2344 ),
2345 ConstraintValuePathComponent::TupleElement {
2346 composite_type_id,
2347 ordinal,
2348 } => (
2349 DiagnosticFactTag::TupleElement,
2350 diagnostic_code::pack_u32_pair(composite_type_id, ordinal),
2351 ),
2352 ConstraintValuePathComponent::Newtype { composite_type_id } => {
2353 (DiagnosticFactTag::Newtype, u64::from(composite_type_id))
2354 }
2355 ConstraintValuePathComponent::EnumVariant {
2356 enum_type_id,
2357 variant_id,
2358 } => (
2359 DiagnosticFactTag::EnumVariant,
2360 diagnostic_code::pack_u32_pair(enum_type_id, variant_id),
2361 ),
2362 ConstraintValuePathComponent::ListElement { index } => {
2363 (DiagnosticFactTag::ListElement, u64::from(index))
2364 }
2365 ConstraintValuePathComponent::SetElement { index } => {
2366 (DiagnosticFactTag::SetElement, u64::from(index))
2367 }
2368 ConstraintValuePathComponent::MapEntryKey { index } => {
2369 (DiagnosticFactTag::MapEntryKey, u64::from(index))
2370 }
2371 ConstraintValuePathComponent::MapEntryValue { index } => {
2372 (DiagnosticFactTag::MapEntryValue, u64::from(index))
2373 }
2374 }
2375}
2376
2377pub enum ErrorDetail {
2385 DiagnosticFacts(Box<DiagnosticFactDetail>),
2387 Executor(ExecutorErrorDetail),
2389 Store(StoreError),
2390 Query(QueryErrorDetail),
2391 Recovery(RecoveryErrorDetail),
2392 }
2395
2396pub enum ExecutorErrorDetail {
2398 MutationRequiredFieldMissing,
2400 MutationManagedTimestampRegression,
2402 MutationDatabaseOwnedFieldExplicit,
2404 MutationBatchEmpty,
2406 MutationBatchTooManyItems,
2408 MutationBatchStagedBytesExceeded,
2410 MutationBatchResultBytesExceeded,
2412 MutationBatchStoreMismatch,
2414 MutationBatchTooManyEntities,
2416 MutationBatchDuplicateKey,
2418 AcceptedRowConstraintProgramCorrupt,
2420}
2421
2422pub enum RecoveryErrorDetail {
2429 UnsupportedFormatVersion { found: Option<u16>, required: u16 },
2430
2431 MalformedFormatMarker { reason: RecoveryFormatMarkerError },
2432}
2433
2434#[derive(Clone, Copy, Eq, PartialEq)]
2436pub enum RecoveryFormatMarkerError {
2437 Magic,
2438 Checksum,
2439 State,
2440}
2441
2442impl RecoveryFormatMarkerError {
2443 const fn diagnostic_decode_reason(self) -> diagnostic_code::DiagnosticDecodeReason {
2444 match self {
2445 Self::Magic => diagnostic_code::DiagnosticDecodeReason::RecoveryMarkerMagic,
2446 Self::Checksum => diagnostic_code::DiagnosticDecodeReason::RecoveryMarkerChecksum,
2447 Self::State => diagnostic_code::DiagnosticDecodeReason::RecoveryMarkerState,
2448 }
2449 }
2450}
2451
2452pub enum StoreError {
2460 NotFound,
2461
2462 Corrupt,
2463
2464 InvariantViolation,
2465
2466 SchemaDdlPublicationRaceLost,
2467
2468 SchemaDdlRewriteRequiresMigration,
2469
2470 SchemaMigration {
2471 reason: diagnostic_code::SchemaMigrationCode,
2472 },
2473
2474 SchemaRowLayoutVersionExhausted,
2475
2476 JournalMutationRevisionExhausted,
2477
2478 SchemaTransitionBudgetExceeded {
2479 resource: SchemaTransitionBudgetResource,
2480 },
2481
2482 SchemaGeneratedFieldAfterDdlField,
2484
2485 SchemaGeneratedConstraintActivationStale,
2487}
2488
2489pub enum QueryErrorDetail {
2496 NumericOverflow,
2497
2498 NumericNotRepresentable,
2499
2500 UnsupportedSqlFeature {
2501 feature: diagnostic_code::SqlFeatureCode,
2502 },
2503
2504 SqlLowering {
2505 reason: diagnostic_code::SqlLoweringCode,
2506 },
2507
2508 UnsupportedProjection {
2509 reason: diagnostic_code::QueryProjectionCode,
2510 },
2511
2512 UnknownAggregateTargetField,
2513
2514 QueryReadAdmission {
2515 reason: diagnostic_code::QueryReadAdmissionCode,
2516 },
2517
2518 SqlSurfaceMismatch {
2519 mismatch: diagnostic_code::SqlSurfaceMismatchCode,
2520 },
2521
2522 SqlWriteBoundary {
2523 boundary: diagnostic_code::SqlWriteBoundaryCode,
2524 },
2525
2526 SchemaDdlAdmission {
2527 error: SchemaDdlAdmissionError,
2528 },
2529
2530 StaleSchemaRevision,
2531}
2532
2533impl fmt::Display for QueryErrorDetail {
2534 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2535 f.write_str(COMPACT_QUERY_DIAGNOSTIC_MESSAGE)
2536 }
2537}
2538
2539impl std::error::Error for QueryErrorDetail {}
2540
2541#[derive(Clone, Copy, Debug, Eq, PartialEq)]
2549pub enum SchemaTransitionBudgetResource {
2550 DeletionKeys,
2552 ProjectionEntries,
2554 ProjectionWorkUnits,
2556 SourceRows,
2558 SourceRowBytes,
2560 StagedRawBytes,
2562}
2563
2564#[derive(Clone, Copy, Eq, PartialEq)]
2573pub enum SchemaDdlAdmissionError {
2574 MissingExpectedSchemaVersion,
2575
2576 MissingNextSchemaVersion,
2577
2578 StaleExpectedSchemaVersion,
2579
2580 InvalidExpectedSchemaVersion,
2581
2582 InvalidNextSchemaVersion,
2583
2584 AcceptedSchemaChangeWithoutVersionBump,
2585
2586 EmptyVersionBump,
2587
2588 VersionGap,
2589
2590 VersionRollback,
2591
2592 FingerprintMethodMismatch,
2593
2594 UnsupportedTransitionClass,
2595
2596 PhysicalRunnerMissing,
2597
2598 ValidationFailed,
2599
2600 PublicationRaceLost,
2601
2602 InvalidAddColumnDefault,
2603
2604 InvalidAlterColumnDefault,
2605
2606 RowLayoutVersionExhausted,
2607
2608 GeneratedIndexDropRejected,
2609
2610 SchemaRewriteRequiresMigration,
2611
2612 SchemaTransitionBudgetExceeded {
2613 resource: SchemaTransitionBudgetResource,
2614 },
2615
2616 GeneratedFieldDefaultChangeRejected,
2617
2618 GeneratedFieldNullabilityChangeRejected,
2619}
2620
2621impl fmt::Display for SchemaDdlAdmissionError {
2622 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2623 f.write_str(COMPACT_QUERY_DIAGNOSTIC_MESSAGE)
2624 }
2625}
2626
2627impl std::error::Error for SchemaDdlAdmissionError {}
2628
2629impl fmt::Debug for ErrorDetail {
2630 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2631 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2632 }
2633}
2634
2635impl fmt::Debug for ExecutorErrorDetail {
2636 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2637 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2638 }
2639}
2640
2641impl fmt::Debug for StoreError {
2642 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2643 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2644 }
2645}
2646
2647impl fmt::Debug for QueryErrorDetail {
2648 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2649 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2650 }
2651}
2652
2653impl fmt::Debug for RecoveryErrorDetail {
2654 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2655 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2656 }
2657}
2658
2659impl fmt::Debug for RecoveryFormatMarkerError {
2660 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2661 fmt_compact_diagnostic(
2662 f,
2663 diagnostic_code::DiagnosticCode::RuntimeCorruption,
2664 Some(diagnostic_code::DiagnosticDetail::RuntimeKind {
2665 kind: diagnostic_code::RuntimeErrorKind::Corruption,
2666 }),
2667 )
2668 }
2669}
2670
2671impl fmt::Debug for SchemaDdlAdmissionError {
2672 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2673 fmt_compact_diagnostic(
2674 f,
2675 diagnostic_code::DiagnosticCode::SchemaDdlAdmission,
2676 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2677 reason: self.diagnostic_code(),
2678 }),
2679 )
2680 }
2681}
2682
2683fn fmt_compact_diagnostic(
2684 f: &mut fmt::Formatter<'_>,
2685 code: diagnostic_code::DiagnosticCode,
2686 detail: Option<diagnostic_code::DiagnosticDetail>,
2687) -> fmt::Result {
2688 write!(
2689 f,
2690 "{}",
2691 diagnostic_code::ErrorCode::from_parts(code, detail).raw()
2692 )
2693}
2694
2695impl ErrorDetail {
2696 #[must_use]
2698 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2699 match self {
2700 Self::DiagnosticFacts(detail) => detail.diagnostic.code(),
2701 Self::Executor(error) => error.diagnostic_code(),
2702 Self::Store(error) => error.diagnostic_code(),
2703 Self::Query(error) => error.diagnostic_code(),
2704 Self::Recovery(error) => error.diagnostic_code(),
2705 }
2706 }
2707
2708 #[must_use]
2710 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2711 match self {
2712 Self::DiagnosticFacts(detail) => detail.diagnostic.detail().copied(),
2713 Self::Executor(error) => error.diagnostic_detail(),
2714 Self::Store(error) => error.diagnostic_detail(),
2715 Self::Query(error) => error.diagnostic_detail(),
2716 Self::Recovery(error) => error.diagnostic_detail(),
2717 }
2718 }
2719
2720 #[must_use]
2722 #[cold]
2723 #[inline(never)]
2724 pub fn diagnostic_facts(&self) -> Vec<(diagnostic_code::DiagnosticFactTag, u64)> {
2725 match self {
2726 Self::DiagnosticFacts(detail) => detail.facts.clone(),
2727 Self::Executor(error) => error.diagnostic_facts(),
2728 Self::Query(error) => error.diagnostic_facts(),
2729 Self::Recovery(error) => error.diagnostic_facts(),
2730 Self::Store(_) => Vec::new(),
2731 }
2732 }
2733}
2734
2735impl ExecutorErrorDetail {
2736 #[must_use]
2738 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2739 match self {
2740 Self::MutationRequiredFieldMissing
2741 | Self::MutationDatabaseOwnedFieldExplicit
2742 | Self::MutationBatchEmpty
2743 | Self::MutationBatchTooManyItems
2744 | Self::MutationBatchTooManyEntities
2745 | Self::MutationBatchStagedBytesExceeded
2746 | Self::MutationBatchResultBytesExceeded => {
2747 diagnostic_code::DiagnosticCode::RuntimeUnsupported
2748 }
2749 Self::MutationBatchStoreMismatch | Self::MutationBatchDuplicateKey => {
2750 diagnostic_code::DiagnosticCode::RuntimeConflict
2751 }
2752 Self::MutationManagedTimestampRegression => {
2753 diagnostic_code::DiagnosticCode::RuntimeInvariantViolation
2754 }
2755 Self::AcceptedRowConstraintProgramCorrupt => {
2756 diagnostic_code::DiagnosticCode::RuntimeCorruption
2757 }
2758 }
2759 }
2760
2761 #[must_use]
2763 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2764 match self {
2765 Self::MutationRequiredFieldMissing => {
2766 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2767 boundary: diagnostic_code::RuntimeBoundaryCode::MutationRequiredFieldMissing,
2768 })
2769 }
2770 Self::MutationDatabaseOwnedFieldExplicit => {
2771 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2772 boundary:
2773 diagnostic_code::RuntimeBoundaryCode::MutationDatabaseOwnedFieldExplicit,
2774 })
2775 }
2776 Self::MutationBatchEmpty => Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2777 boundary: diagnostic_code::RuntimeBoundaryCode::MutationBatchEmpty,
2778 }),
2779 Self::MutationBatchTooManyItems => {
2780 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2781 boundary: diagnostic_code::RuntimeBoundaryCode::MutationBatchTooManyItems,
2782 })
2783 }
2784 Self::MutationBatchStagedBytesExceeded => {
2785 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2786 boundary:
2787 diagnostic_code::RuntimeBoundaryCode::MutationBatchStagedBytesExceeded,
2788 })
2789 }
2790 Self::MutationBatchResultBytesExceeded => {
2791 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2792 boundary:
2793 diagnostic_code::RuntimeBoundaryCode::MutationBatchResultBytesExceeded,
2794 })
2795 }
2796 Self::MutationBatchStoreMismatch => {
2797 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2798 boundary: diagnostic_code::RuntimeBoundaryCode::MutationBatchStoreMismatch,
2799 })
2800 }
2801 Self::MutationBatchTooManyEntities => {
2802 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2803 boundary: diagnostic_code::RuntimeBoundaryCode::MutationBatchTooManyEntities,
2804 })
2805 }
2806 Self::MutationBatchDuplicateKey => {
2807 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2808 boundary: diagnostic_code::RuntimeBoundaryCode::MutationBatchDuplicateKey,
2809 })
2810 }
2811 Self::MutationManagedTimestampRegression => {
2812 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2813 boundary:
2814 diagnostic_code::RuntimeBoundaryCode::MutationManagedTimestampRegression,
2815 })
2816 }
2817 Self::AcceptedRowConstraintProgramCorrupt => {
2818 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2819 boundary:
2820 diagnostic_code::RuntimeBoundaryCode::AcceptedRowConstraintProgramCorrupt,
2821 })
2822 }
2823 }
2824 }
2825
2826 #[must_use]
2828 #[cold]
2829 #[inline(never)]
2830 pub const fn diagnostic_facts(&self) -> Vec<(diagnostic_code::DiagnosticFactTag, u64)> {
2831 Vec::new()
2832 }
2833}
2834
2835impl RecoveryErrorDetail {
2836 #[must_use]
2838 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2839 match self {
2840 Self::UnsupportedFormatVersion { .. } => {
2841 diagnostic_code::DiagnosticCode::RuntimeIncompatiblePersistedFormat
2842 }
2843 Self::MalformedFormatMarker { .. } => {
2844 diagnostic_code::DiagnosticCode::RuntimeCorruption
2845 }
2846 }
2847 }
2848
2849 #[must_use]
2851 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2852 let kind = match self {
2853 Self::UnsupportedFormatVersion { .. } => {
2854 diagnostic_code::RuntimeErrorKind::IncompatiblePersistedFormat
2855 }
2856 Self::MalformedFormatMarker { .. } => diagnostic_code::RuntimeErrorKind::Corruption,
2857 };
2858
2859 Some(diagnostic_code::DiagnosticDetail::RuntimeKind { kind })
2860 }
2861
2862 #[must_use]
2864 pub fn diagnostic_facts(&self) -> Vec<(diagnostic_code::DiagnosticFactTag, u64)> {
2865 match self {
2866 Self::UnsupportedFormatVersion { found, required } => {
2867 let mut facts = Vec::with_capacity(usize::from(found.is_some()) + 1);
2868 facts.push((
2869 diagnostic_code::DiagnosticFactTag::ExpectedVersion,
2870 u64::from(*required),
2871 ));
2872 if let Some(found) = found {
2873 facts.push((
2874 diagnostic_code::DiagnosticFactTag::ActualVersion,
2875 u64::from(*found),
2876 ));
2877 }
2878 facts
2879 }
2880 Self::MalformedFormatMarker { reason } => vec![(
2881 diagnostic_code::DiagnosticFactTag::DecodeReason,
2882 reason.diagnostic_decode_reason().raw(),
2883 )],
2884 }
2885 }
2886}
2887
2888impl StoreError {
2889 #[must_use]
2891 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2892 match self {
2893 Self::NotFound => diagnostic_code::DiagnosticCode::StoreNotFound,
2894 Self::Corrupt => diagnostic_code::DiagnosticCode::StoreCorruption,
2895 Self::InvariantViolation => diagnostic_code::DiagnosticCode::StoreInvariantViolation,
2896 Self::SchemaDdlPublicationRaceLost
2897 | Self::SchemaDdlRewriteRequiresMigration
2898 | Self::SchemaRowLayoutVersionExhausted
2899 | Self::SchemaTransitionBudgetExceeded { .. } => {
2900 diagnostic_code::DiagnosticCode::SchemaDdlAdmission
2901 }
2902 Self::JournalMutationRevisionExhausted | Self::SchemaGeneratedFieldAfterDdlField => {
2903 diagnostic_code::DiagnosticCode::RuntimeUnsupported
2904 }
2905 Self::SchemaGeneratedConstraintActivationStale => {
2906 diagnostic_code::DiagnosticCode::RuntimeConflict
2907 }
2908 Self::SchemaMigration { reason } => reason.diagnostic_code(),
2909 }
2910 }
2911
2912 #[must_use]
2914 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2915 match self {
2916 Self::SchemaDdlPublicationRaceLost => {
2917 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2918 reason: diagnostic_code::SchemaDdlAdmissionCode::PublicationRaceLost,
2919 })
2920 }
2921 Self::SchemaDdlRewriteRequiresMigration => {
2922 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2923 reason: diagnostic_code::SchemaDdlAdmissionCode::SchemaRewriteRequiresMigration,
2924 })
2925 }
2926 Self::SchemaMigration { reason } => {
2927 Some(diagnostic_code::DiagnosticDetail::SchemaMigration { reason: *reason })
2928 }
2929 Self::SchemaRowLayoutVersionExhausted => {
2930 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2931 reason: diagnostic_code::SchemaDdlAdmissionCode::RowLayoutVersionExhausted,
2932 })
2933 }
2934 Self::JournalMutationRevisionExhausted => {
2935 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2936 boundary:
2937 diagnostic_code::RuntimeBoundaryCode::JournalMutationRevisionExhausted,
2938 })
2939 }
2940 Self::SchemaTransitionBudgetExceeded { .. } => {
2941 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2942 reason: diagnostic_code::SchemaDdlAdmissionCode::SchemaTransitionBudgetExceeded,
2943 })
2944 }
2945 Self::SchemaGeneratedFieldAfterDdlField => {
2946 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2947 boundary: diagnostic_code::RuntimeBoundaryCode::GeneratedFieldAfterDdlField,
2948 })
2949 }
2950 Self::SchemaGeneratedConstraintActivationStale => {
2951 Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2952 boundary:
2953 diagnostic_code::RuntimeBoundaryCode::GeneratedConstraintActivationStale,
2954 })
2955 }
2956 Self::NotFound | Self::Corrupt | Self::InvariantViolation => None,
2957 }
2958 }
2959}
2960
2961impl QueryErrorDetail {
2962 #[must_use]
2964 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2965 match self {
2966 Self::NumericOverflow => diagnostic_code::DiagnosticCode::QueryNumericOverflow,
2967 Self::NumericNotRepresentable => {
2968 diagnostic_code::DiagnosticCode::QueryNumericNotRepresentable
2969 }
2970 Self::UnsupportedSqlFeature { .. } => {
2971 diagnostic_code::DiagnosticCode::QueryUnsupportedSqlFeature
2972 }
2973 Self::SqlLowering { .. } => diagnostic_code::DiagnosticCode::QueryUnsupportedSqlFeature,
2974 Self::UnsupportedProjection { .. } => {
2975 diagnostic_code::DiagnosticCode::QueryUnsupportedProjection
2976 }
2977 Self::UnknownAggregateTargetField => {
2978 diagnostic_code::DiagnosticCode::QueryUnknownAggregateTargetField
2979 }
2980 Self::QueryReadAdmission { .. } => diagnostic_code::DiagnosticCode::QueryReadAdmission,
2981 Self::SqlSurfaceMismatch { .. } => {
2982 diagnostic_code::DiagnosticCode::QuerySqlSurfaceMismatch
2983 }
2984 Self::SqlWriteBoundary { .. } => diagnostic_code::DiagnosticCode::QuerySqlWriteBoundary,
2985 Self::SchemaDdlAdmission { .. } => diagnostic_code::DiagnosticCode::SchemaDdlAdmission,
2986 Self::StaleSchemaRevision => diagnostic_code::DiagnosticCode::RuntimeConflict,
2987 }
2988 }
2989
2990 #[must_use]
2992 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2993 match self {
2994 Self::UnsupportedSqlFeature { feature } => {
2995 Some(diagnostic_code::DiagnosticDetail::UnsupportedSqlFeature { feature: *feature })
2996 }
2997 Self::SqlLowering { reason } => {
2998 Some(diagnostic_code::DiagnosticDetail::SqlLowering { reason: *reason })
2999 }
3000 Self::UnsupportedProjection { reason } => {
3001 Some(diagnostic_code::DiagnosticDetail::QueryProjection { reason: *reason })
3002 }
3003 Self::QueryReadAdmission { reason } => {
3004 Some(diagnostic_code::DiagnosticDetail::QueryReadAdmission { reason: *reason })
3005 }
3006 Self::SqlSurfaceMismatch { mismatch } => {
3007 Some(diagnostic_code::DiagnosticDetail::SqlSurfaceMismatch {
3008 mismatch: *mismatch,
3009 })
3010 }
3011 Self::SqlWriteBoundary { boundary } => {
3012 Some(diagnostic_code::DiagnosticDetail::SqlWriteBoundary {
3013 boundary: *boundary,
3014 })
3015 }
3016 Self::SchemaDdlAdmission { error } => {
3017 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
3018 reason: error.diagnostic_code(),
3019 })
3020 }
3021 Self::NumericOverflow
3022 | Self::NumericNotRepresentable
3023 | Self::UnknownAggregateTargetField
3024 | Self::StaleSchemaRevision => None,
3025 }
3026 }
3027
3028 #[must_use]
3030 #[cold]
3031 #[inline(never)]
3032 pub const fn diagnostic_facts(&self) -> Vec<(diagnostic_code::DiagnosticFactTag, u64)> {
3033 Vec::new()
3034 }
3035}
3036
3037impl SchemaDdlAdmissionError {
3038 #[must_use]
3040 pub const fn diagnostic_code(&self) -> diagnostic_code::SchemaDdlAdmissionCode {
3041 match self {
3042 Self::MissingExpectedSchemaVersion => {
3043 diagnostic_code::SchemaDdlAdmissionCode::MissingExpectedSchemaVersion
3044 }
3045 Self::MissingNextSchemaVersion => {
3046 diagnostic_code::SchemaDdlAdmissionCode::MissingNextSchemaVersion
3047 }
3048 Self::StaleExpectedSchemaVersion => {
3049 diagnostic_code::SchemaDdlAdmissionCode::StaleExpectedSchemaVersion
3050 }
3051 Self::InvalidExpectedSchemaVersion => {
3052 diagnostic_code::SchemaDdlAdmissionCode::InvalidExpectedSchemaVersion
3053 }
3054 Self::InvalidNextSchemaVersion => {
3055 diagnostic_code::SchemaDdlAdmissionCode::InvalidNextSchemaVersion
3056 }
3057 Self::AcceptedSchemaChangeWithoutVersionBump => {
3058 diagnostic_code::SchemaDdlAdmissionCode::AcceptedSchemaChangeWithoutVersionBump
3059 }
3060 Self::EmptyVersionBump => diagnostic_code::SchemaDdlAdmissionCode::EmptyVersionBump,
3061 Self::VersionGap => diagnostic_code::SchemaDdlAdmissionCode::VersionGap,
3062 Self::VersionRollback => diagnostic_code::SchemaDdlAdmissionCode::VersionRollback,
3063 Self::FingerprintMethodMismatch => {
3064 diagnostic_code::SchemaDdlAdmissionCode::FingerprintMethodMismatch
3065 }
3066 Self::UnsupportedTransitionClass => {
3067 diagnostic_code::SchemaDdlAdmissionCode::UnsupportedTransitionClass
3068 }
3069 Self::PhysicalRunnerMissing => {
3070 diagnostic_code::SchemaDdlAdmissionCode::PhysicalRunnerMissing
3071 }
3072 Self::ValidationFailed => diagnostic_code::SchemaDdlAdmissionCode::ValidationFailed,
3073 Self::PublicationRaceLost => {
3074 diagnostic_code::SchemaDdlAdmissionCode::PublicationRaceLost
3075 }
3076 Self::InvalidAddColumnDefault => {
3077 diagnostic_code::SchemaDdlAdmissionCode::InvalidAddColumnDefault
3078 }
3079 Self::InvalidAlterColumnDefault => {
3080 diagnostic_code::SchemaDdlAdmissionCode::InvalidAlterColumnDefault
3081 }
3082 Self::GeneratedIndexDropRejected => {
3083 diagnostic_code::SchemaDdlAdmissionCode::GeneratedIndexDropRejected
3084 }
3085 Self::SchemaRewriteRequiresMigration => {
3086 diagnostic_code::SchemaDdlAdmissionCode::SchemaRewriteRequiresMigration
3087 }
3088 Self::SchemaTransitionBudgetExceeded { .. } => {
3089 diagnostic_code::SchemaDdlAdmissionCode::SchemaTransitionBudgetExceeded
3090 }
3091 Self::GeneratedFieldDefaultChangeRejected => {
3092 diagnostic_code::SchemaDdlAdmissionCode::GeneratedFieldDefaultChangeRejected
3093 }
3094 Self::GeneratedFieldNullabilityChangeRejected => {
3095 diagnostic_code::SchemaDdlAdmissionCode::GeneratedFieldNullabilityChangeRejected
3096 }
3097 Self::RowLayoutVersionExhausted => {
3098 diagnostic_code::SchemaDdlAdmissionCode::RowLayoutVersionExhausted
3099 }
3100 }
3101 }
3102}
3103
3104#[repr(u8)]
3111#[derive(Clone, Copy, Eq, PartialEq)]
3112pub enum ErrorClass {
3113 Corruption,
3114 IncompatiblePersistedFormat,
3115 NotFound,
3116 Internal,
3117 Conflict,
3118 Unsupported,
3119 InvariantViolation,
3120}
3121
3122impl ErrorClass {
3123 #[must_use]
3125 pub const fn diagnostic_code(self, origin: ErrorOrigin) -> diagnostic_code::DiagnosticCode {
3126 match self {
3127 Self::Corruption if matches!(origin, ErrorOrigin::Store) => {
3128 diagnostic_code::DiagnosticCode::StoreCorruption
3129 }
3130 Self::Corruption => diagnostic_code::DiagnosticCode::RuntimeCorruption,
3131 Self::IncompatiblePersistedFormat => {
3132 diagnostic_code::DiagnosticCode::RuntimeIncompatiblePersistedFormat
3133 }
3134 Self::NotFound if matches!(origin, ErrorOrigin::Store) => {
3135 diagnostic_code::DiagnosticCode::StoreNotFound
3136 }
3137 Self::NotFound => diagnostic_code::DiagnosticCode::RuntimeNotFound,
3138 Self::Internal => diagnostic_code::DiagnosticCode::RuntimeInternal,
3139 Self::Conflict => diagnostic_code::DiagnosticCode::RuntimeConflict,
3140 Self::Unsupported if matches!(origin, ErrorOrigin::Cursor) => {
3141 diagnostic_code::DiagnosticCode::QueryInvalidContinuationCursor
3142 }
3143 Self::Unsupported => diagnostic_code::DiagnosticCode::RuntimeUnsupported,
3144 Self::InvariantViolation if matches!(origin, ErrorOrigin::Store) => {
3145 diagnostic_code::DiagnosticCode::StoreInvariantViolation
3146 }
3147 Self::InvariantViolation => diagnostic_code::DiagnosticCode::RuntimeInvariantViolation,
3148 }
3149 }
3150}
3151
3152impl fmt::Debug for ErrorClass {
3153 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3154 write!(f, "{}", *self as u8)
3155 }
3156}
3157
3158#[repr(u8)]
3165#[derive(Clone, Copy, Eq, PartialEq)]
3166pub enum ErrorOrigin {
3167 Serialize,
3168 Store,
3169 Index,
3170 Identity,
3171 Query,
3172 Planner,
3173 Cursor,
3174 Recovery,
3175 Response,
3176 Executor,
3177 Interface,
3178}
3179
3180impl ErrorOrigin {
3181 #[must_use]
3183 pub const fn diagnostic_origin(self) -> diagnostic_code::ErrorOrigin {
3184 match self {
3185 Self::Serialize => diagnostic_code::ErrorOrigin::Serialize,
3186 Self::Store => diagnostic_code::ErrorOrigin::Store,
3187 Self::Index => diagnostic_code::ErrorOrigin::Index,
3188 Self::Identity => diagnostic_code::ErrorOrigin::Identity,
3189 Self::Query => diagnostic_code::ErrorOrigin::Query,
3190 Self::Planner => diagnostic_code::ErrorOrigin::Planner,
3191 Self::Cursor => diagnostic_code::ErrorOrigin::Cursor,
3192 Self::Recovery => diagnostic_code::ErrorOrigin::Recovery,
3193 Self::Response => diagnostic_code::ErrorOrigin::Response,
3194 Self::Executor => diagnostic_code::ErrorOrigin::Executor,
3195 Self::Interface => diagnostic_code::ErrorOrigin::Interface,
3196 }
3197 }
3198}
3199
3200impl fmt::Debug for ErrorOrigin {
3201 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3202 write!(f, "{}", *self as u8)
3203 }
3204}