Skip to main content

icydb_core/error/
mod.rs

1//! Module: error
2//!
3//! Defines the canonical runtime error taxonomy for `icydb-core`.
4//! This module owns the shared error classes, origins, details, and
5//! constructor entry points used across storage, planning, execution, and
6//! serialization boundaries.
7
8#[cfg(test)]
9mod tests;
10
11use icydb_diagnostic_code as diagnostic_code;
12use std::fmt;
13
14pub(crate) const COMPACT_QUERY_DIAGNOSTIC_MESSAGE: &str = "query diagnostic";
15const COMPACT_RUNTIME_DIAGNOSTIC_MESSAGE: &str = "runtime diagnostic";
16const COMPACT_STORE_DIAGNOSTIC_MESSAGE: &str = "store diagnostic";
17const COMPACT_INDEX_DIAGNOSTIC_MESSAGE: &str = "index diagnostic";
18const COMPACT_SERIALIZE_DIAGNOSTIC_MESSAGE: &str = "serialize diagnostic";
19const COMPACT_IDENTITY_DIAGNOSTIC_MESSAGE: &str = "identity diagnostic";
20
21const fn compact_message_for(_class: ErrorClass, origin: ErrorOrigin) -> &'static str {
22    match origin {
23        ErrorOrigin::Serialize => COMPACT_SERIALIZE_DIAGNOSTIC_MESSAGE,
24        ErrorOrigin::Store => COMPACT_STORE_DIAGNOSTIC_MESSAGE,
25        ErrorOrigin::Index => COMPACT_INDEX_DIAGNOSTIC_MESSAGE,
26        ErrorOrigin::Identity => COMPACT_IDENTITY_DIAGNOSTIC_MESSAGE,
27        ErrorOrigin::Query | ErrorOrigin::Planner | ErrorOrigin::Response => {
28            COMPACT_QUERY_DIAGNOSTIC_MESSAGE
29        }
30        ErrorOrigin::Cursor
31        | ErrorOrigin::Recovery
32        | ErrorOrigin::Executor
33        | ErrorOrigin::Interface => COMPACT_RUNTIME_DIAGNOSTIC_MESSAGE,
34    }
35}
36
37// ============================================================================
38// INTERNAL ERROR TAXONOMY — ARCHITECTURAL CONTRACT
39// ============================================================================
40//
41// This file defines the canonical runtime error classification system for
42// icydb-core. It is the single source of truth for:
43//
44//   • ErrorClass   (semantic domain)
45//   • ErrorOrigin  (subsystem boundary)
46//   • Structured detail payloads
47//   • Canonical constructor entry points
48//
49// -----------------------------------------------------------------------------
50// DESIGN INTENT
51// -----------------------------------------------------------------------------
52//
53// 1. InternalError is a *taxonomy carrier*, not a formatting utility.
54//
55//    - ErrorClass represents semantic meaning (corruption, invariant_violation,
56//      unsupported, etc).
57//    - ErrorOrigin represents the subsystem boundary (store, index, query,
58//      executor, serialize, interface, etc).
59//    - The (class, origin) pair must remain stable and intentional.
60//
61// 2. Call sites MUST prefer canonical constructors.
62//
63//    Do NOT construct errors manually via:
64//        InternalError::new(class, origin)
65//    unless you are defining a new canonical helper here.
66//
67//    If a pattern appears more than once, centralize it here.
68//
69// 3. Constructors in this file must represent real architectural boundaries.
70//
71//    Add a new helper ONLY if it:
72//
73//      • Encodes a cross-cutting invariant,
74//      • Represents a subsystem boundary,
75//      • Or prevents taxonomy drift across call sites.
76//
77//    Do NOT add feature-specific helpers.
78//    Do NOT add one-off formatting helpers.
79//    Do NOT turn this file into a generic message factory.
80//
81// 4. ErrorDetail must align with ErrorOrigin.
82//
83//    If detail is present, it MUST correspond to the origin.
84//    Do not attach mismatched detail variants.
85//
86// 5. Plan-layer errors are NOT runtime failures.
87//
88//    PlanError and CursorPlanError must be translated into
89//    executor/query invariants via the canonical mapping functions.
90//    Do not leak plan-layer error types across execution boundaries.
91//
92// 6. Preserve taxonomy stability.
93//
94//    Do NOT:
95//      • Merge error classes.
96//      • Reclassify corruption as internal.
97//      • Downgrade invariant violations.
98//      • Introduce ambiguous class/origin combinations.
99//
100//    Any change to ErrorClass or ErrorOrigin is an architectural change
101//    and must be reviewed accordingly.
102//
103// -----------------------------------------------------------------------------
104// NON-GOALS
105// -----------------------------------------------------------------------------
106//
107// This is NOT:
108//
109//   • A public API contract.
110//   • A generic error abstraction layer.
111//   • A feature-specific message builder.
112//   • A dumping ground for temporary error conversions.
113//
114// -----------------------------------------------------------------------------
115// MAINTENANCE GUIDELINES
116// -----------------------------------------------------------------------------
117//
118// When modifying this file:
119//
120//   1. Ensure classification semantics remain consistent.
121//   2. Avoid constructor proliferation.
122//   3. Prefer narrow, origin-specific helpers over ad-hoc new(...).
123//   4. Keep formatting minimal and standardized.
124//   5. Keep this file boring and stable.
125//
126// If this file grows rapidly, something is wrong at the call sites.
127//
128// ============================================================================
129
130///
131/// InternalError
132///
133/// Structured runtime error with a stable internal classification.
134/// Not a stable API; intended for internal use and may change without notice.
135///
136
137pub struct InternalError {
138    pub(crate) class: ErrorClass,
139    pub(crate) origin: ErrorOrigin,
140
141    /// Optional structured error detail.
142    /// The variant (if present) must correspond to `origin`.
143    pub(crate) detail: Option<ErrorDetail>,
144}
145
146#[expect(
147    clippy::missing_const_for_fn,
148    reason = "internal error constructors stay non-const so compact diagnostic construction does not force const churn across subsystem helper seams"
149)]
150impl InternalError {
151    /// Construct an InternalError with optional origin-specific detail.
152    /// This constructor provides default StoreError details for certain
153    /// (class, origin) combinations but does not guarantee a detail payload.
154    #[must_use]
155    #[cold]
156    #[inline(never)]
157    pub fn new(class: ErrorClass, origin: ErrorOrigin) -> Self {
158        let detail = match (class, origin) {
159            (ErrorClass::Corruption, ErrorOrigin::Store) => {
160                Some(ErrorDetail::Store(StoreError::Corrupt))
161            }
162            (ErrorClass::InvariantViolation, ErrorOrigin::Store) => {
163                Some(ErrorDetail::Store(StoreError::InvariantViolation))
164            }
165            _ => None,
166        };
167
168        Self {
169            class,
170            origin,
171            detail,
172        }
173    }
174
175    /// Return the internal error class taxonomy.
176    #[must_use]
177    pub const fn class(&self) -> ErrorClass {
178        self.class
179    }
180
181    /// Return the internal error origin taxonomy.
182    #[must_use]
183    pub const fn origin(&self) -> ErrorOrigin {
184        self.origin
185    }
186
187    /// Return the rendered internal error message.
188    #[must_use]
189    pub const fn message(&self) -> &'static str {
190        compact_message_for(self.class, self.origin)
191    }
192
193    /// Return the optional structured detail payload.
194    #[must_use]
195    pub const fn detail(&self) -> Option<&ErrorDetail> {
196        self.detail.as_ref()
197    }
198
199    /// Return compact diagnostic identity for this internal error.
200    #[must_use]
201    pub fn diagnostic(&self) -> diagnostic_code::Diagnostic {
202        diagnostic_code::Diagnostic::new(
203            self.diagnostic_code(),
204            self.origin.diagnostic_origin(),
205            self.detail
206                .as_ref()
207                .and_then(ErrorDetail::diagnostic_detail),
208        )
209    }
210
211    /// Return the compact diagnostic code for this internal error.
212    #[must_use]
213    pub fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
214        self.detail.as_ref().map_or_else(
215            || self.class.diagnostic_code(self.origin),
216            ErrorDetail::diagnostic_code,
217        )
218    }
219
220    /// Consume and return the rendered internal error message.
221    #[must_use]
222    pub fn into_message(self) -> String {
223        self.message().to_string()
224    }
225
226    /// Construct an error while preserving an explicit class/origin taxonomy pair.
227    #[cold]
228    #[inline(never)]
229    pub(crate) fn classified(class: ErrorClass, origin: ErrorOrigin) -> Self {
230        Self::new(class, origin)
231    }
232
233    /// Rebuild this error with a new origin while preserving class taxonomy.
234    ///
235    /// Origin-scoped detail payloads are intentionally dropped when re-origining.
236    #[cold]
237    #[inline(never)]
238    pub(crate) fn with_origin(self, origin: ErrorOrigin) -> Self {
239        Self::classified(self.class, origin)
240    }
241
242    /// Construct an index-origin invariant violation.
243    #[cold]
244    #[inline(never)]
245    pub(crate) fn index_invariant() -> Self {
246        Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Index)
247    }
248
249    /// Construct the canonical index field-count invariant for key building.
250    pub(crate) fn index_key_field_count_exceeds_max(
251        _index_name: &str,
252        _field_count: usize,
253        _max_fields: usize,
254    ) -> Self {
255        Self::index_invariant()
256    }
257
258    /// Construct the canonical index-key source-field-missing-on-model invariant.
259    pub(crate) fn index_key_item_field_missing_on_entity_model(_field: &str) -> Self {
260        Self::index_invariant()
261    }
262
263    /// Construct the canonical index-key source-field-missing-on-row invariant.
264    pub(crate) fn index_key_item_field_missing_on_lookup_row(_field: &str) -> Self {
265        Self::index_invariant()
266    }
267
268    /// Construct the canonical index-expression source-type mismatch invariant.
269    pub(crate) fn index_expression_source_type_mismatch(
270        _index_name: &str,
271        _expression: impl Sized,
272        _expected: impl Sized,
273        _source_label: &str,
274    ) -> Self {
275        Self::index_invariant()
276    }
277
278    /// Construct a planner-origin invariant violation for executor-boundary
279    /// contract drift.
280    #[cold]
281    #[inline(never)]
282    pub(crate) fn planner_executor_invariant() -> Self {
283        Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Planner)
284    }
285
286    /// Construct a query-origin invariant violation for executor-boundary
287    /// contract drift.
288    #[cold]
289    #[inline(never)]
290    pub(crate) fn query_executor_invariant() -> Self {
291        Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Query)
292    }
293
294    /// Construct a cursor-origin invariant violation for executor-boundary
295    /// contract drift.
296    #[cold]
297    #[inline(never)]
298    pub(crate) fn cursor_executor_invariant() -> Self {
299        Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Cursor)
300    }
301
302    /// Construct an executor-origin invariant violation.
303    #[cold]
304    #[inline(never)]
305    pub(crate) fn executor_invariant() -> Self {
306        Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Executor)
307    }
308
309    /// Construct an executor-origin internal error.
310    #[cold]
311    #[inline(never)]
312    pub(crate) fn executor_internal() -> Self {
313        Self::new(ErrorClass::Internal, ErrorOrigin::Executor)
314    }
315
316    /// Construct an executor-origin unsupported error.
317    #[cold]
318    #[inline(never)]
319    pub(crate) fn executor_unsupported() -> Self {
320        Self::new(ErrorClass::Unsupported, ErrorOrigin::Executor)
321    }
322
323    /// Construct an executor-origin save-preflight primary-key missing invariant.
324    pub(crate) fn mutation_entity_primary_key_missing(
325        _entity_path: &str,
326        _field_name: &str,
327    ) -> Self {
328        Self::executor_invariant()
329    }
330
331    /// Construct an executor-origin save-preflight primary-key invalid-value invariant.
332    pub(crate) fn mutation_entity_primary_key_invalid_value(
333        _entity_path: &str,
334        _field_name: &str,
335        _value: &crate::value::Value,
336    ) -> Self {
337        Self::executor_invariant()
338    }
339
340    /// Construct an executor-origin save-preflight primary-key type mismatch invariant.
341    pub(crate) fn mutation_entity_primary_key_type_mismatch(
342        _entity_path: &str,
343        _field_name: &str,
344        _value: &crate::value::Value,
345    ) -> Self {
346        Self::executor_invariant()
347    }
348
349    /// Construct an executor-origin save-preflight primary-key identity mismatch invariant.
350    pub(crate) fn mutation_entity_primary_key_mismatch(
351        _entity_path: &str,
352        _field_name: &str,
353        _field_value: &crate::value::Value,
354        _identity_key: &crate::value::Value,
355    ) -> Self {
356        Self::executor_invariant()
357    }
358
359    /// Construct an executor-origin save-preflight field-missing invariant.
360    pub(crate) fn mutation_entity_field_missing(
361        _entity_path: &str,
362        _field_name: &str,
363        _indexed: bool,
364    ) -> Self {
365        Self::executor_invariant()
366    }
367
368    /// Construct an executor-origin sparse structural patch required-field invariant.
369    pub(crate) fn mutation_structural_patch_required_field_missing(
370        _entity_path: &str,
371        _field_name: &str,
372    ) -> Self {
373        Self::executor_invariant()
374    }
375
376    /// Construct an executor-origin save-preflight field-type mismatch invariant.
377    pub(crate) fn mutation_entity_field_type_mismatch(
378        _entity_path: &str,
379        _field_name: &str,
380        _value: &crate::value::Value,
381    ) -> Self {
382        Self::executor_invariant()
383    }
384
385    /// Construct an executor-origin generated-field authored-write rejection.
386    pub(crate) fn mutation_generated_field_explicit(_entity_path: &str, _field_name: &str) -> Self {
387        Self::executor_unsupported()
388    }
389
390    /// Construct an executor-origin typed create omission rejection.
391    #[must_use]
392    pub fn mutation_create_missing_authored_fields(_entity_path: &str, _field_names: &str) -> Self {
393        Self::executor_unsupported()
394    }
395
396    /// Construct an executor-origin mutation result invariant.
397    ///
398    /// This constructor lands ahead of the public structural mutation surface,
399    /// so the library target may not route through it until that caller exists.
400    pub(crate) fn mutation_structural_after_image_invalid(
401        _entity_path: &str,
402        _data_key: impl Sized,
403        _detail: impl Sized,
404    ) -> Self {
405        Self::executor_invariant()
406    }
407
408    /// Construct an executor-origin mutation unknown-field invariant.
409    pub(crate) fn mutation_structural_field_unknown(_entity_path: &str, _field_name: &str) -> Self {
410        Self::executor_invariant()
411    }
412
413    /// Construct an executor-origin save-preflight decimal-scale unsupported error.
414    pub(crate) fn mutation_decimal_scale_mismatch(
415        _entity_path: &str,
416        _field_name: &str,
417        _expected_scale: impl Sized,
418        _actual_scale: impl Sized,
419    ) -> Self {
420        Self::executor_unsupported()
421    }
422
423    /// Construct an executor-origin save-preflight text-length unsupported error.
424    pub(crate) fn mutation_text_max_len_exceeded(
425        _entity_path: &str,
426        _field_name: &str,
427        _max_len: impl Sized,
428        _actual_len: impl Sized,
429    ) -> Self {
430        Self::executor_unsupported()
431    }
432
433    /// Construct an executor-origin save-preflight set-encoding invariant.
434    pub(crate) fn mutation_set_field_list_required(_entity_path: &str, _field_name: &str) -> Self {
435        Self::executor_invariant()
436    }
437
438    /// Construct an executor-origin save-preflight set-canonicality invariant.
439    pub(crate) fn mutation_set_field_not_canonical(_entity_path: &str, _field_name: &str) -> Self {
440        Self::executor_invariant()
441    }
442
443    /// Construct an executor-origin save-preflight map-encoding invariant.
444    pub(crate) fn mutation_map_field_map_required(_entity_path: &str, _field_name: &str) -> Self {
445        Self::executor_invariant()
446    }
447
448    /// Construct an executor-origin save-preflight map-entry invariant.
449    pub(crate) fn mutation_map_field_entries_invalid(
450        _entity_path: &str,
451        _field_name: &str,
452        _detail: impl Sized,
453    ) -> Self {
454        Self::executor_invariant()
455    }
456
457    /// Construct an executor-origin save-preflight map-canonicality invariant.
458    pub(crate) fn mutation_map_field_entries_not_canonical(
459        _entity_path: &str,
460        _field_name: &str,
461    ) -> Self {
462        Self::executor_invariant()
463    }
464
465    /// Construct a query-origin scalar page invariant for ordering before filtering.
466    pub(crate) fn scalar_page_ordering_after_filtering_required() -> Self {
467        Self::query_executor_invariant()
468    }
469
470    /// Construct a query-origin scalar page invariant for missing order at the cursor boundary.
471    pub(crate) fn scalar_page_cursor_boundary_order_required() -> Self {
472        Self::query_executor_invariant()
473    }
474
475    /// Construct a query-origin scalar page invariant for cursor-before-ordering drift.
476    pub(crate) fn scalar_page_cursor_boundary_after_ordering_required() -> Self {
477        Self::query_executor_invariant()
478    }
479
480    /// Construct a query-origin scalar page invariant for pagination-before-ordering drift.
481    pub(crate) fn scalar_page_pagination_after_ordering_required() -> Self {
482        Self::query_executor_invariant()
483    }
484
485    /// Construct a query-origin scalar page invariant for delete-limit-before-ordering drift.
486    pub(crate) fn scalar_page_delete_limit_after_ordering_required() -> Self {
487        Self::query_executor_invariant()
488    }
489
490    /// Construct a query-origin load-runtime invariant for scalar-mode payload mismatch.
491    pub(crate) fn load_runtime_scalar_payload_required() -> Self {
492        Self::query_executor_invariant()
493    }
494
495    /// Construct a query-origin load-runtime invariant for grouped-mode payload mismatch.
496    pub(crate) fn load_runtime_grouped_payload_required() -> Self {
497        Self::query_executor_invariant()
498    }
499
500    /// Construct a query-origin load-surface invariant for scalar-page payload mismatch.
501    pub(crate) fn load_runtime_scalar_surface_payload_required() -> Self {
502        Self::query_executor_invariant()
503    }
504
505    /// Construct a query-origin load-surface invariant for grouped-page payload mismatch.
506    pub(crate) fn load_runtime_grouped_surface_payload_required() -> Self {
507        Self::query_executor_invariant()
508    }
509
510    /// Construct a query-origin load-entrypoint invariant for non-load plans.
511    pub(crate) fn load_executor_load_plan_required() -> Self {
512        Self::query_executor_invariant()
513    }
514
515    /// Construct an executor-origin delete-entrypoint unsupported grouped-mode error.
516    pub(crate) fn delete_executor_grouped_unsupported() -> Self {
517        Self::executor_unsupported()
518    }
519
520    /// Construct a query-origin delete-entrypoint invariant for non-delete plans.
521    pub(crate) fn delete_executor_delete_plan_required() -> Self {
522        Self::query_executor_invariant()
523    }
524
525    /// Construct a query-origin aggregate kernel invariant for fold-mode contract drift.
526    pub(crate) fn aggregate_fold_mode_terminal_contract_required() -> Self {
527        Self::query_executor_invariant()
528    }
529
530    /// Construct a query-origin fast-stream invariant for route kind/request mismatch.
531    pub(crate) fn fast_stream_route_kind_request_match_required() -> Self {
532        Self::query_executor_invariant()
533    }
534
535    /// Construct a query-origin scan invariant for missing index-prefix executable specs.
536    pub(crate) fn secondary_index_prefix_spec_required() -> Self {
537        Self::query_executor_invariant()
538    }
539
540    /// Construct a query-origin scan invariant for missing index-range executable specs.
541    pub(crate) fn index_range_limit_spec_required() -> Self {
542        Self::query_executor_invariant()
543    }
544
545    /// Construct an executor-origin mutation unsupported error for duplicate atomic save keys.
546    pub(crate) fn mutation_atomic_save_duplicate_key(_entity_path: &str, _key: impl Sized) -> Self {
547        Self::executor_unsupported()
548    }
549
550    /// Construct an executor-origin mutation invariant for index-store generation drift.
551    pub(crate) fn mutation_index_store_generation_changed(
552        _expected_generation: u64,
553        _observed_generation: u64,
554    ) -> Self {
555        Self::executor_invariant()
556    }
557
558    /// Construct a planner-origin invariant violation.
559    #[cold]
560    #[inline(never)]
561    pub(crate) fn planner_invariant() -> Self {
562        Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Planner)
563    }
564
565    /// Construct a planner-origin invalid-logical-plan invariant.
566    pub(crate) fn query_invalid_logical_plan() -> Self {
567        Self::planner_invariant()
568    }
569
570    /// Construct a store-origin invariant violation.
571    pub(crate) fn store_invariant() -> Self {
572        Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Store)
573    }
574
575    /// Construct the canonical duplicate runtime-hook entity-tag invariant.
576    pub(crate) fn duplicate_runtime_hooks_for_entity_tag(
577        _entity_tag: crate::types::EntityTag,
578    ) -> Self {
579        Self::store_invariant()
580    }
581
582    /// Construct the canonical duplicate runtime-hook entity-path invariant.
583    pub(crate) fn duplicate_runtime_hooks_for_entity_path(_entity_path: &str) -> Self {
584        Self::store_invariant()
585    }
586
587    /// Construct a store-origin internal error.
588    #[cold]
589    #[inline(never)]
590    pub(crate) fn store_internal() -> Self {
591        Self::new(ErrorClass::Internal, ErrorOrigin::Store)
592    }
593
594    /// Construct the canonical unconfigured commit-memory id internal error.
595    pub(crate) fn commit_memory_id_unconfigured() -> Self {
596        Self::store_internal()
597    }
598
599    /// Construct the canonical commit-memory id mismatch internal error.
600    pub(crate) fn commit_memory_id_mismatch(_cached_id: u8, _configured_id: u8) -> Self {
601        Self::store_internal()
602    }
603
604    /// Construct the canonical commit-memory stable-key mismatch internal error.
605    pub(crate) fn commit_memory_stable_key_mismatch(
606        _cached_key: &str,
607        _configured_key: &str,
608    ) -> Self {
609        Self::store_internal()
610    }
611
612    /// Construct a recovery-origin incompatible store-format error.
613    pub(crate) fn recovery_unsupported_database_format(found: Option<u16>, required: u16) -> Self {
614        Self {
615            class: ErrorClass::IncompatiblePersistedFormat,
616            origin: ErrorOrigin::Recovery,
617            detail: Some(ErrorDetail::Recovery(
618                RecoveryErrorDetail::UnsupportedFormatVersion { found, required },
619            )),
620        }
621    }
622
623    /// Construct a recovery-origin malformed store-format marker error.
624    pub(crate) fn recovery_malformed_database_format_marker(
625        reason: RecoveryFormatMarkerError,
626    ) -> Self {
627        Self {
628            class: ErrorClass::Corruption,
629            origin: ErrorOrigin::Recovery,
630            detail: Some(ErrorDetail::Recovery(
631                RecoveryErrorDetail::MalformedFormatMarker { reason },
632            )),
633        }
634    }
635
636    /// Construct a recovery-origin boot control-memory failure.
637    pub(crate) fn recovery_database_format_control_unavailable() -> Self {
638        Self::new(ErrorClass::Internal, ErrorOrigin::Recovery)
639    }
640
641    /// Construct a commit control-memory growth failure.
642    pub(crate) fn commit_control_memory_growth_failed() -> Self {
643        Self::store_internal()
644    }
645
646    /// Construct a store-format memory registration failure.
647    #[cfg(not(test))]
648    pub(crate) fn database_format_memory_registration_failed(_err: impl Sized) -> Self {
649        Self::store_internal()
650    }
651
652    /// Construct the canonical missing rollback-row invariant for delete execution.
653    pub(crate) fn delete_rollback_row_required() -> Self {
654        Self::store_internal()
655    }
656
657    /// Construct the canonical recovery-integrity totals corruption error.
658    pub(crate) fn recovery_integrity_validation_failed(
659        _missing_index_entries: u64,
660        _divergent_index_entries: u64,
661        _orphan_index_references: u64,
662    ) -> Self {
663        Self::store_corruption()
664    }
665
666    /// Construct an index-origin internal error.
667    #[cold]
668    #[inline(never)]
669    pub(crate) fn index_internal() -> Self {
670        Self::new(ErrorClass::Internal, ErrorOrigin::Index)
671    }
672
673    /// Construct the canonical missing old entity-key internal error for structural index removal.
674    pub(crate) fn structural_index_removal_entity_key_required() -> Self {
675        Self::index_internal()
676    }
677
678    /// Construct the canonical missing new entity-key internal error for structural index insertion.
679    pub(crate) fn structural_index_insertion_entity_key_required() -> Self {
680        Self::index_internal()
681    }
682
683    /// Construct the canonical missing old entity-key internal error for index commit-op removal.
684    pub(crate) fn index_commit_op_old_entity_key_required() -> Self {
685        Self::index_internal()
686    }
687
688    /// Construct the canonical missing new entity-key internal error for index commit-op insertion.
689    pub(crate) fn index_commit_op_new_entity_key_required() -> Self {
690        Self::index_internal()
691    }
692
693    /// Construct a query-origin internal error.
694    #[cfg(test)]
695    pub(crate) fn query_internal() -> Self {
696        Self::new(ErrorClass::Internal, ErrorOrigin::Query)
697    }
698
699    /// Construct a query-origin unsupported error.
700    #[cold]
701    #[inline(never)]
702    pub(crate) fn query_unsupported() -> Self {
703        Self::new(ErrorClass::Unsupported, ErrorOrigin::Query)
704    }
705
706    /// Construct a query-origin conflict for execution against a superseded
707    /// accepted schema revision.
708    #[cfg(feature = "sql")]
709    pub(crate) fn query_stale_accepted_schema_revision(
710        _expected_revision: u64,
711        _current_revision: Option<u64>,
712    ) -> Self {
713        Self {
714            class: ErrorClass::Conflict,
715            origin: ErrorOrigin::Query,
716            detail: Some(ErrorDetail::Query(QueryErrorDetail::StaleSchemaRevision)),
717        }
718    }
719
720    /// Construct a query-origin SQL DDL admission error with structured detail.
721    #[cold]
722    #[inline(never)]
723    #[cfg(feature = "sql")]
724    pub(crate) fn query_schema_ddl_admission(error: SchemaDdlAdmissionError) -> Self {
725        Self {
726            class: ErrorClass::Unsupported,
727            origin: ErrorOrigin::Query,
728            detail: Some(ErrorDetail::Query(QueryErrorDetail::SchemaDdlAdmission {
729                error,
730            })),
731        }
732    }
733
734    /// Construct a query-origin numeric overflow error with structured detail.
735    #[cold]
736    #[inline(never)]
737    pub(crate) fn query_numeric_overflow() -> Self {
738        Self {
739            class: ErrorClass::Unsupported,
740            origin: ErrorOrigin::Query,
741            detail: Some(ErrorDetail::Query(QueryErrorDetail::NumericOverflow)),
742        }
743    }
744
745    /// Construct a query-origin non-representable numeric result error with
746    /// structured detail.
747    #[cold]
748    #[inline(never)]
749    pub(crate) fn query_numeric_not_representable() -> Self {
750        Self {
751            class: ErrorClass::Unsupported,
752            origin: ErrorOrigin::Query,
753            detail: Some(ErrorDetail::Query(
754                QueryErrorDetail::NumericNotRepresentable,
755            )),
756        }
757    }
758
759    /// Construct a serialize-origin internal error.
760    #[cold]
761    #[inline(never)]
762    pub(crate) fn serialize_internal() -> Self {
763        Self::new(ErrorClass::Internal, ErrorOrigin::Serialize)
764    }
765
766    /// Construct the canonical persisted-row encode internal error.
767    pub(crate) fn persisted_row_encode_failed(_detail: impl Sized) -> Self {
768        Self::persisted_row_encode_internal()
769    }
770
771    /// Construct the compact persisted-row encode internal error.
772    pub(crate) fn persisted_row_encode_internal() -> Self {
773        Self::serialize_internal()
774    }
775
776    /// Construct the canonical persisted-row field encode internal error.
777    pub(crate) fn persisted_row_field_encode_failed(field_name: &str, _detail: impl Sized) -> Self {
778        Self::persisted_row_field_encode_internal(field_name)
779    }
780
781    /// Construct the compact persisted-row field encode internal error.
782    pub(crate) fn persisted_row_field_encode_internal(_field_name: &str) -> Self {
783        Self::persisted_row_encode_internal()
784    }
785
786    /// Construct the canonical bytes(field) value encode internal error.
787    pub(crate) fn bytes_field_value_encode_failed(_detail: impl Sized) -> Self {
788        Self::serialize_internal()
789    }
790
791    /// Construct a store-origin corruption error.
792    #[cold]
793    #[inline(never)]
794    pub(crate) fn store_corruption() -> Self {
795        Self::new(ErrorClass::Corruption, ErrorOrigin::Store)
796    }
797
798    /// Construct a store-origin commit-marker corruption error.
799    pub(crate) fn commit_corruption() -> Self {
800        Self::store_corruption()
801    }
802
803    /// Construct a store-origin commit-marker component corruption error.
804    pub(crate) fn commit_component_corruption() -> Self {
805        Self::commit_corruption()
806    }
807
808    /// Construct the canonical commit-marker id generation internal error.
809    pub(crate) fn commit_id_generation_failed() -> Self {
810        Self::store_internal()
811    }
812
813    /// Construct the canonical commit-marker payload u32-length-limit error.
814    pub(crate) fn commit_marker_payload_exceeds_u32_length_limit() -> Self {
815        Self::store_unsupported()
816    }
817
818    /// Construct the canonical commit-marker component invalid-length corruption error.
819    pub(crate) fn commit_component_length_invalid() -> Self {
820        Self::commit_corruption()
821    }
822
823    /// Construct the canonical commit-marker max-size corruption error.
824    pub(crate) fn commit_marker_exceeds_max_size() -> Self {
825        Self::commit_corruption()
826    }
827
828    /// Construct the canonical commit-control slot max-size unsupported error.
829    pub(crate) fn commit_control_slot_exceeds_max_size() -> Self {
830        Self::store_unsupported()
831    }
832
833    /// Construct the canonical commit-control marker-bytes length-limit error.
834    pub(crate) fn commit_control_slot_marker_bytes_exceed_u32_length_limit() -> Self {
835        Self::store_unsupported()
836    }
837
838    /// Construct the canonical startup index-rebuild invalid-data-key corruption error.
839    pub(crate) fn startup_index_rebuild_invalid_data_key() -> Self {
840        Self::store_corruption()
841    }
842
843    /// Construct an index-origin corruption error.
844    #[cold]
845    #[inline(never)]
846    pub(crate) fn index_corruption() -> Self {
847        Self::new(ErrorClass::Corruption, ErrorOrigin::Index)
848    }
849
850    /// Construct the canonical unique-validation corruption wrapper.
851    pub(crate) fn index_unique_validation_corruption() -> Self {
852        Self::index_plan_index_corruption()
853    }
854
855    /// Construct the canonical structural index-entry corruption wrapper.
856    pub(crate) fn structural_index_entry_corruption() -> Self {
857        Self::index_plan_index_corruption()
858    }
859
860    /// Construct the canonical missing new entity-key invariant during unique validation.
861    pub(crate) fn index_unique_validation_entity_key_required() -> Self {
862        Self::index_invariant()
863    }
864
865    /// Construct the canonical unique-validation structural row-decode corruption error.
866    pub(crate) fn index_unique_validation_row_deserialize_failed() -> Self {
867        Self::index_plan_serialize_corruption()
868    }
869
870    /// Construct the canonical unique-validation primary-key slot decode corruption error.
871    pub(crate) fn index_unique_validation_primary_key_decode_failed() -> Self {
872        Self::index_plan_serialize_corruption()
873    }
874
875    /// Construct the canonical unique-validation stored key rebuild corruption error.
876    pub(crate) fn index_unique_validation_key_rebuild_failed() -> Self {
877        Self::index_plan_serialize_corruption()
878    }
879
880    /// Construct the canonical unique-validation missing-row corruption error.
881    pub(crate) fn index_unique_validation_row_required() -> Self {
882        Self::index_plan_store_corruption()
883    }
884
885    /// Construct the canonical index-only predicate missing-component invariant.
886    pub(crate) fn index_only_predicate_component_required() -> Self {
887        Self::index_invariant()
888    }
889
890    /// Construct the canonical index-scan continuation-envelope invariant.
891    pub(crate) fn index_scan_continuation_anchor_within_envelope_required() -> Self {
892        Self::index_invariant()
893    }
894
895    /// Construct the canonical index-scan continuation-advancement invariant.
896    pub(crate) fn index_scan_continuation_advancement_required() -> Self {
897        Self::index_invariant()
898    }
899
900    /// Construct the canonical index-scan key-decode corruption error.
901    pub(crate) fn index_scan_key_corrupted_during(
902        _context: &'static str,
903        _err: impl Sized,
904    ) -> Self {
905        Self::index_corruption()
906    }
907
908    /// Construct the canonical index-scan missing projection-component invariant.
909    pub(crate) fn index_projection_component_required(
910        _index_name: &str,
911        _component_index: usize,
912    ) -> Self {
913        Self::index_invariant()
914    }
915
916    /// Construct the canonical scan-time index-entry decode corruption error.
917    pub(crate) fn index_entry_decode_failed() -> Self {
918        Self::index_corruption()
919    }
920
921    /// Construct a serialize-origin corruption error.
922    pub(crate) fn serialize_corruption() -> Self {
923        Self::new(ErrorClass::Corruption, ErrorOrigin::Serialize)
924    }
925
926    /// Construct the canonical persisted-row decode corruption error.
927    pub(crate) fn persisted_row_decode_failed(_detail: impl Sized) -> Self {
928        Self::persisted_row_decode_corruption()
929    }
930
931    /// Construct the compact persisted-row decode corruption error.
932    pub(crate) fn persisted_row_decode_corruption() -> Self {
933        Self::serialize_corruption()
934    }
935
936    /// Construct the canonical persisted-row field decode corruption error.
937    pub(crate) fn persisted_row_field_decode_failed(field_name: &str, _detail: impl Sized) -> Self {
938        Self::persisted_row_field_decode_corruption(field_name)
939    }
940
941    /// Construct the compact persisted-row field decode corruption error.
942    pub(crate) fn persisted_row_field_decode_corruption(_field_name: &str) -> Self {
943        Self::persisted_row_decode_corruption()
944    }
945
946    /// Construct the canonical persisted-row field-kind decode corruption error.
947    pub(crate) fn persisted_row_field_kind_decode_failed(
948        field_name: &str,
949        _field_kind: impl fmt::Debug,
950        _detail: impl Sized,
951    ) -> Self {
952        Self::persisted_row_field_decode_corruption(field_name)
953    }
954
955    /// Construct the canonical persisted-row scalar-payload length corruption error.
956    pub(crate) fn persisted_row_field_payload_exact_len_required(field_name: &str) -> Self {
957        Self::persisted_row_field_decode_corruption(field_name)
958    }
959
960    /// Construct the canonical persisted-row scalar-payload empty-body corruption error.
961    pub(crate) fn persisted_row_field_payload_must_be_empty(field_name: &str) -> Self {
962        Self::persisted_row_field_decode_corruption(field_name)
963    }
964
965    /// Construct the canonical persisted-row scalar-payload invalid-byte corruption error.
966    pub(crate) fn persisted_row_field_payload_invalid_byte(field_name: &str) -> Self {
967        Self::persisted_row_field_decode_corruption(field_name)
968    }
969
970    /// Construct the canonical persisted-row scalar-payload non-finite corruption error.
971    pub(crate) fn persisted_row_field_payload_non_finite(field_name: &str) -> Self {
972        Self::persisted_row_field_decode_corruption(field_name)
973    }
974
975    /// Construct the canonical persisted-row scalar-payload out-of-range corruption error.
976    pub(crate) fn persisted_row_field_payload_out_of_range(field_name: &str) -> Self {
977        Self::persisted_row_field_decode_corruption(field_name)
978    }
979
980    /// Construct the canonical persisted-row invalid text payload corruption error.
981    pub(crate) fn persisted_row_field_text_payload_invalid_utf8(field_name: &str) -> Self {
982        Self::persisted_row_field_decode_corruption(field_name)
983    }
984
985    /// Construct the canonical persisted-row structural slot-lookup invariant.
986    pub(crate) fn persisted_row_slot_lookup_out_of_bounds(_model_path: &str, _slot: usize) -> Self {
987        Self::index_invariant()
988    }
989
990    /// Construct the canonical persisted-row structural slot-cache invariant.
991    pub(crate) fn persisted_row_slot_cache_lookup_out_of_bounds(
992        _model_path: &str,
993        _slot: usize,
994    ) -> Self {
995        Self::index_invariant()
996    }
997
998    /// Construct the canonical persisted-row primary-key decode corruption error.
999    pub(crate) fn persisted_row_primary_key_not_primary_key_encodable(
1000        _data_key: impl fmt::Debug,
1001        _detail: impl Sized,
1002    ) -> Self {
1003        Self::persisted_row_decode_corruption()
1004    }
1005
1006    /// Construct the canonical persisted-row missing primary-key slot corruption error.
1007    pub(crate) fn persisted_row_primary_key_slot_missing(_data_key: impl fmt::Debug) -> Self {
1008        Self::persisted_row_decode_corruption()
1009    }
1010
1011    /// Construct the canonical persisted-row key mismatch corruption error.
1012    pub(crate) fn persisted_row_key_mismatch() -> Self {
1013        Self::store_corruption()
1014    }
1015
1016    /// Construct the canonical persisted-row missing declared-field corruption error.
1017    pub(crate) fn persisted_row_declared_field_missing(field_name: &str) -> Self {
1018        Self::persisted_row_field_decode_corruption(field_name)
1019    }
1020
1021    /// Construct the canonical data-key entity mismatch corruption error.
1022    pub(crate) fn data_key_entity_mismatch() -> Self {
1023        Self::store_corruption()
1024    }
1025
1026    /// Construct the canonical reverse-index ordinal overflow internal error.
1027    pub(crate) fn reverse_index_ordinal_overflow(
1028        _source_path: &str,
1029        _field_name: &str,
1030        _target_path: &str,
1031        _detail: impl Sized,
1032    ) -> Self {
1033        Self::index_internal()
1034    }
1035
1036    /// Construct the canonical reverse-index entry corruption error.
1037    pub(crate) fn reverse_index_entry_corrupted(
1038        _source_path: &str,
1039        _field_name: &str,
1040        _target_path: &str,
1041        _index_key: impl fmt::Debug,
1042        _detail: impl Sized,
1043    ) -> Self {
1044        Self::index_corruption()
1045    }
1046
1047    /// Construct the canonical relation-target store missing internal error.
1048    pub(crate) fn relation_target_store_missing(
1049        _source_path: &str,
1050        _field_name: &str,
1051        _target_path: &str,
1052        _store_path: &str,
1053        _detail: impl Sized,
1054    ) -> Self {
1055        Self::executor_internal()
1056    }
1057
1058    /// Construct the canonical relation-target key decode corruption error.
1059    pub(crate) fn relation_target_key_decode_failed(
1060        _context_label: &str,
1061        _source_path: &str,
1062        _field_name: &str,
1063        _target_path: &str,
1064        _detail: impl Sized,
1065    ) -> Self {
1066        Self::identity_corruption()
1067    }
1068
1069    /// Construct the canonical relation-target entity mismatch corruption error.
1070    pub(crate) fn relation_target_entity_mismatch(
1071        _context_label: &str,
1072        _source_path: &str,
1073        _field_name: &str,
1074        _target_path: &str,
1075        _target_entity_name: &str,
1076        _expected_tag: impl Sized,
1077        _actual_tag: impl Sized,
1078    ) -> Self {
1079        Self::store_corruption()
1080    }
1081
1082    /// Construct the canonical relation-source row decode corruption error.
1083    pub(crate) fn relation_source_row_decode_failed(
1084        _source_path: &str,
1085        _field_name: &str,
1086        _target_path: &str,
1087        _detail: impl Sized,
1088    ) -> Self {
1089        Self::persisted_row_decode_corruption()
1090    }
1091
1092    /// Construct the canonical relation-source unsupported scalar relation-key corruption error.
1093    pub(crate) fn relation_source_row_unsupported_scalar_relation_key(
1094        _source_path: &str,
1095        _field_name: &str,
1096        _target_path: &str,
1097    ) -> Self {
1098        Self::persisted_row_decode_corruption()
1099    }
1100
1101    /// Construct the canonical unsupported strong-relation key-kind corruption error.
1102    pub(crate) fn relation_source_row_unsupported_key_kind(_field_kind: impl fmt::Debug) -> Self {
1103        Self::persisted_row_decode_corruption()
1104    }
1105
1106    /// Construct the canonical reverse-index relation-target decode invariant failure.
1107    pub(crate) fn reverse_index_relation_target_decode_invariant_violated(
1108        _source_path: &str,
1109        _field_name: &str,
1110        _target_path: &str,
1111    ) -> Self {
1112        Self::executor_internal()
1113    }
1114
1115    /// Construct the canonical covering-component empty-payload corruption error.
1116    pub(crate) fn bytes_covering_component_payload_empty() -> Self {
1117        Self::index_corruption()
1118    }
1119
1120    /// Construct the canonical covering-component truncated bool corruption error.
1121    pub(crate) fn bytes_covering_bool_payload_truncated() -> Self {
1122        Self::index_corruption()
1123    }
1124
1125    /// Construct the canonical covering-component invalid-length corruption error.
1126    pub(crate) fn bytes_covering_component_payload_invalid_length() -> Self {
1127        Self::index_corruption()
1128    }
1129
1130    /// Construct the canonical covering-component invalid-bool corruption error.
1131    pub(crate) fn bytes_covering_bool_payload_invalid_value() -> Self {
1132        Self::index_corruption()
1133    }
1134
1135    /// Construct the canonical covering-component invalid text terminator corruption error.
1136    pub(crate) fn bytes_covering_text_payload_invalid_terminator() -> Self {
1137        Self::index_corruption()
1138    }
1139
1140    /// Construct the canonical covering-component trailing-text corruption error.
1141    pub(crate) fn bytes_covering_text_payload_trailing_bytes() -> Self {
1142        Self::index_corruption()
1143    }
1144
1145    /// Construct the canonical covering-component invalid-UTF-8 text corruption error.
1146    pub(crate) fn bytes_covering_text_payload_invalid_utf8() -> Self {
1147        Self::index_corruption()
1148    }
1149
1150    /// Construct the canonical covering-component invalid text escape corruption error.
1151    pub(crate) fn bytes_covering_text_payload_invalid_escape_byte() -> Self {
1152        Self::index_corruption()
1153    }
1154
1155    /// Construct the canonical covering-component missing text terminator corruption error.
1156    pub(crate) fn bytes_covering_text_payload_missing_terminator() -> Self {
1157        Self::index_corruption()
1158    }
1159
1160    /// Construct the canonical missing persisted-field decode error.
1161    #[must_use]
1162    pub fn missing_persisted_slot(field_name: &'static str) -> Self {
1163        Self::persisted_row_field_decode_corruption(field_name)
1164    }
1165
1166    /// Construct an identity-origin corruption error.
1167    pub(crate) fn identity_corruption() -> Self {
1168        Self::new(ErrorClass::Corruption, ErrorOrigin::Identity)
1169    }
1170
1171    /// Construct a store-origin unsupported error.
1172    #[cold]
1173    #[inline(never)]
1174    pub(crate) fn store_unsupported() -> Self {
1175        Self::new(ErrorClass::Unsupported, ErrorOrigin::Store)
1176    }
1177
1178    /// Construct the canonical schema DDL publication race error.
1179    #[cfg(any(test, feature = "sql"))]
1180    pub(crate) fn schema_ddl_publication_race_lost(_entity_path: &'static str) -> Self {
1181        Self {
1182            class: ErrorClass::Unsupported,
1183            origin: ErrorOrigin::Store,
1184            detail: Some(ErrorDetail::Store(StoreError::SchemaDdlPublicationRaceLost)),
1185        }
1186    }
1187
1188    /// Construct the canonical SQL DDL SET NOT NULL validation failure.
1189    #[cfg(feature = "sql")]
1190    pub(crate) fn schema_ddl_set_not_null_validation_failed(
1191        _entity_path: &'static str,
1192        _column_name: &str,
1193    ) -> Self {
1194        Self {
1195            class: ErrorClass::Unsupported,
1196            origin: ErrorOrigin::Store,
1197            detail: Some(ErrorDetail::Store(
1198                StoreError::SchemaDdlSetNotNullValidationFailed,
1199            )),
1200        }
1201    }
1202
1203    /// Construct the canonical unsupported persisted entity-tag store error.
1204    pub(crate) fn unsupported_entity_tag_in_data_store(
1205        _entity_tag: crate::types::EntityTag,
1206    ) -> Self {
1207        Self::store_unsupported()
1208    }
1209
1210    /// Construct the canonical commit-memory id registration failure.
1211    #[cfg(not(test))]
1212    pub(crate) fn commit_memory_id_registration_failed(_err: impl Sized) -> Self {
1213        Self::store_internal()
1214    }
1215
1216    /// Construct an index-origin unsupported error.
1217    pub(crate) fn index_unsupported() -> Self {
1218        Self::new(ErrorClass::Unsupported, ErrorOrigin::Index)
1219    }
1220
1221    /// Construct the canonical index-key component size-limit unsupported error.
1222    pub(crate) fn index_component_exceeds_max_size() -> Self {
1223        Self::index_unsupported()
1224    }
1225
1226    /// Construct a serialize-origin unsupported error.
1227    pub(crate) fn serialize_unsupported() -> Self {
1228        Self::new(ErrorClass::Unsupported, ErrorOrigin::Serialize)
1229    }
1230
1231    /// Construct a cursor-origin unsupported error.
1232    pub(crate) fn cursor_unsupported() -> Self {
1233        Self::new(ErrorClass::Unsupported, ErrorOrigin::Cursor)
1234    }
1235
1236    /// Construct a serialize-origin incompatible persisted-format error.
1237    pub(crate) fn serialize_incompatible_persisted_format() -> Self {
1238        Self::new(
1239            ErrorClass::IncompatiblePersistedFormat,
1240            ErrorOrigin::Serialize,
1241        )
1242    }
1243
1244    /// Construct a query-origin unsupported error preserving one SQL parser
1245    /// unsupported-feature code in structured error detail.
1246    #[cfg(feature = "sql")]
1247    pub(crate) fn query_unsupported_sql_feature(feature: diagnostic_code::SqlFeatureCode) -> Self {
1248        Self {
1249            class: ErrorClass::Unsupported,
1250            origin: ErrorOrigin::Query,
1251            detail: Some(ErrorDetail::Query(
1252                QueryErrorDetail::UnsupportedSqlFeature { feature },
1253            )),
1254        }
1255    }
1256
1257    /// Construct a query-origin unsupported SQL lowering error preserving one
1258    /// compact lowering reason in structured error detail.
1259    #[cfg(feature = "sql")]
1260    pub(crate) fn query_sql_lowering(reason: diagnostic_code::SqlLoweringCode) -> Self {
1261        Self {
1262            class: ErrorClass::Unsupported,
1263            origin: ErrorOrigin::Query,
1264            detail: Some(ErrorDetail::Query(QueryErrorDetail::SqlLowering { reason })),
1265        }
1266    }
1267
1268    /// Construct a query-origin unsupported projection error preserving one
1269    /// compact projection reason in structured error detail.
1270    pub(crate) fn query_unsupported_projection(
1271        reason: diagnostic_code::QueryProjectionCode,
1272    ) -> Self {
1273        Self {
1274            class: ErrorClass::Unsupported,
1275            origin: ErrorOrigin::Query,
1276            detail: Some(ErrorDetail::Query(
1277                QueryErrorDetail::UnsupportedProjection { reason },
1278            )),
1279        }
1280    }
1281
1282    /// Construct a query-origin unsupported aggregate target-field error.
1283    pub(crate) fn query_unknown_aggregate_target_field() -> Self {
1284        Self {
1285            class: ErrorClass::Unsupported,
1286            origin: ErrorOrigin::Query,
1287            detail: Some(ErrorDetail::Query(
1288                QueryErrorDetail::UnknownAggregateTargetField,
1289            )),
1290        }
1291    }
1292
1293    /// Construct a query-origin result-shape mismatch error preserving one
1294    /// compact result-shape reason in structured error detail.
1295    pub(crate) fn query_result_shape_mismatch(
1296        reason: diagnostic_code::QueryResultShapeCode,
1297    ) -> Self {
1298        Self {
1299            class: ErrorClass::Unsupported,
1300            origin: ErrorOrigin::Query,
1301            detail: Some(ErrorDetail::Query(QueryErrorDetail::ResultShapeMismatch {
1302                reason,
1303            })),
1304        }
1305    }
1306
1307    /// Construct a query-origin unsupported error preserving one SQL endpoint
1308    /// surface mismatch in structured error detail.
1309    #[cfg(feature = "sql")]
1310    pub(crate) fn query_sql_surface_mismatch(
1311        mismatch: diagnostic_code::SqlSurfaceMismatchCode,
1312    ) -> Self {
1313        Self {
1314            class: ErrorClass::Unsupported,
1315            origin: ErrorOrigin::Query,
1316            detail: Some(ErrorDetail::Query(QueryErrorDetail::SqlSurfaceMismatch {
1317                mismatch,
1318            })),
1319        }
1320    }
1321
1322    /// Construct a query-origin unsupported SQL write boundary error.
1323    #[cfg(feature = "sql")]
1324    pub(crate) fn query_sql_write_boundary(
1325        boundary: diagnostic_code::SqlWriteBoundaryCode,
1326    ) -> Self {
1327        Self {
1328            class: ErrorClass::Unsupported,
1329            origin: ErrorOrigin::Query,
1330            detail: Some(ErrorDetail::Query(QueryErrorDetail::SqlWriteBoundary {
1331                boundary,
1332            })),
1333        }
1334    }
1335
1336    pub fn store_not_found(_key: impl Sized) -> Self {
1337        Self {
1338            class: ErrorClass::NotFound,
1339            origin: ErrorOrigin::Store,
1340            detail: Some(ErrorDetail::Store(StoreError::NotFound)),
1341        }
1342    }
1343
1344    /// Construct a standardized unsupported-entity-path error.
1345    pub fn unsupported_entity_path(_path: impl Sized) -> Self {
1346        Self::store_unsupported()
1347    }
1348
1349    #[must_use]
1350    pub const fn is_not_found(&self) -> bool {
1351        matches!(self.detail, Some(ErrorDetail::Store(StoreError::NotFound)))
1352    }
1353
1354    /// Construct an index-plan corruption error with a canonical prefix.
1355    #[cold]
1356    #[inline(never)]
1357    pub(crate) fn index_plan_corruption(origin: ErrorOrigin) -> Self {
1358        Self::new(ErrorClass::Corruption, origin)
1359    }
1360
1361    /// Construct an index-plan corruption error for index-origin failures.
1362    #[cold]
1363    #[inline(never)]
1364    pub(crate) fn index_plan_index_corruption() -> Self {
1365        Self::index_plan_corruption(ErrorOrigin::Index)
1366    }
1367
1368    /// Construct an index-plan corruption error for store-origin failures.
1369    #[cold]
1370    #[inline(never)]
1371    pub(crate) fn index_plan_store_corruption() -> Self {
1372        Self::index_plan_corruption(ErrorOrigin::Store)
1373    }
1374
1375    /// Construct an index-plan corruption error for serialize-origin failures.
1376    #[cold]
1377    #[inline(never)]
1378    pub(crate) fn index_plan_serialize_corruption() -> Self {
1379        Self::index_plan_corruption(ErrorOrigin::Serialize)
1380    }
1381
1382    /// Construct an index-plan invariant violation error with a canonical prefix.
1383    #[cfg(test)]
1384    pub(crate) fn index_plan_invariant(origin: ErrorOrigin) -> Self {
1385        Self::new(ErrorClass::InvariantViolation, origin)
1386    }
1387
1388    /// Construct an index-plan invariant violation error for store-origin failures.
1389    #[cfg(test)]
1390    pub(crate) fn index_plan_store_invariant() -> Self {
1391        Self::index_plan_invariant(ErrorOrigin::Store)
1392    }
1393
1394    /// Construct an index uniqueness violation conflict error.
1395    pub(crate) fn index_violation(_path: &str, _index_fields: &[&str]) -> Self {
1396        Self::new(ErrorClass::Conflict, ErrorOrigin::Index)
1397    }
1398}
1399
1400impl From<diagnostic_code::QueryReadAdmissionCode> for InternalError {
1401    fn from(reason: diagnostic_code::QueryReadAdmissionCode) -> Self {
1402        Self {
1403            class: ErrorClass::Unsupported,
1404            origin: ErrorOrigin::Query,
1405            detail: Some(ErrorDetail::Query(QueryErrorDetail::QueryReadAdmission {
1406                reason,
1407            })),
1408        }
1409    }
1410}
1411
1412impl fmt::Debug for InternalError {
1413    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1414        fmt_compact_diagnostic(
1415            f,
1416            self.diagnostic_code(),
1417            self.detail
1418                .as_ref()
1419                .and_then(ErrorDetail::diagnostic_detail),
1420        )
1421    }
1422}
1423
1424impl fmt::Display for InternalError {
1425    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1426        f.write_str(self.message())
1427    }
1428}
1429
1430impl std::error::Error for InternalError {}
1431
1432///
1433/// ErrorDetail
1434///
1435/// Structured, origin-specific error detail carried by [`InternalError`].
1436/// This enum is intentionally extensible.
1437///
1438
1439pub enum ErrorDetail {
1440    Store(StoreError),
1441    Query(QueryErrorDetail),
1442    Recovery(RecoveryErrorDetail),
1443    // Future-proofing:
1444    // Index(IndexError),
1445    //
1446    // Executor(ExecutorErrorDetail),
1447}
1448
1449///
1450/// RecoveryErrorDetail
1451///
1452/// Recovery-origin structured error detail payload.
1453///
1454
1455pub enum RecoveryErrorDetail {
1456    UnsupportedFormatVersion { found: Option<u16>, required: u16 },
1457
1458    MalformedFormatMarker { reason: RecoveryFormatMarkerError },
1459}
1460
1461/// Store boot-marker corruption classification.
1462#[derive(Clone, Copy, Eq, PartialEq)]
1463pub enum RecoveryFormatMarkerError {
1464    Magic,
1465    Checksum,
1466    State,
1467}
1468
1469///
1470/// StoreError
1471///
1472/// Store-specific structured error detail.
1473/// Never returned directly; always wrapped in [`ErrorDetail::Store`].
1474///
1475
1476pub enum StoreError {
1477    NotFound,
1478
1479    Corrupt,
1480
1481    InvariantViolation,
1482
1483    SchemaDdlPublicationRaceLost,
1484
1485    SchemaDdlSetNotNullValidationFailed,
1486}
1487
1488///
1489/// QueryErrorDetail
1490///
1491/// Query-origin structured error detail payload.
1492///
1493
1494pub enum QueryErrorDetail {
1495    NumericOverflow,
1496
1497    NumericNotRepresentable,
1498
1499    UnsupportedSqlFeature {
1500        feature: diagnostic_code::SqlFeatureCode,
1501    },
1502
1503    SqlLowering {
1504        reason: diagnostic_code::SqlLoweringCode,
1505    },
1506
1507    UnsupportedProjection {
1508        reason: diagnostic_code::QueryProjectionCode,
1509    },
1510
1511    UnknownAggregateTargetField,
1512
1513    ResultShapeMismatch {
1514        reason: diagnostic_code::QueryResultShapeCode,
1515    },
1516
1517    QueryReadAdmission {
1518        reason: diagnostic_code::QueryReadAdmissionCode,
1519    },
1520
1521    SqlSurfaceMismatch {
1522        mismatch: diagnostic_code::SqlSurfaceMismatchCode,
1523    },
1524
1525    SqlWriteBoundary {
1526        boundary: diagnostic_code::SqlWriteBoundaryCode,
1527    },
1528
1529    SchemaDdlAdmission {
1530        error: SchemaDdlAdmissionError,
1531    },
1532
1533    StaleSchemaRevision,
1534}
1535
1536impl fmt::Display for QueryErrorDetail {
1537    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1538        f.write_str(COMPACT_QUERY_DIAGNOSTIC_MESSAGE)
1539    }
1540}
1541
1542impl std::error::Error for QueryErrorDetail {}
1543
1544///
1545/// SchemaDdlAdmissionError
1546///
1547/// Stable query-visible SQL DDL admission reason. Human diagnostics may carry
1548/// extra version, fingerprint, and target facts beside this machine-readable
1549/// variant.
1550///
1551
1552#[derive(Clone, Copy, Eq, PartialEq)]
1553pub enum SchemaDdlAdmissionError {
1554    MissingExpectedSchemaVersion,
1555
1556    MissingNextSchemaVersion,
1557
1558    StaleExpectedSchemaVersion,
1559
1560    InvalidExpectedSchemaVersion,
1561
1562    InvalidNextSchemaVersion,
1563
1564    AcceptedSchemaChangeWithoutVersionBump,
1565
1566    EmptyVersionBump,
1567
1568    VersionGap,
1569
1570    VersionRollback,
1571
1572    FingerprintMethodMismatch,
1573
1574    UnsupportedTransitionClass,
1575
1576    PhysicalRunnerMissing,
1577
1578    ValidationFailed,
1579
1580    PublicationRaceLost,
1581
1582    InvalidAddColumnDefault,
1583
1584    InvalidAlterColumnDefault,
1585
1586    GeneratedIndexDropRejected,
1587
1588    RequiredDropDefaultUnsupported,
1589
1590    GeneratedFieldDefaultChangeRejected,
1591
1592    GeneratedFieldNullabilityChangeRejected,
1593
1594    SetNotNullValidationFailed,
1595}
1596
1597impl fmt::Display for SchemaDdlAdmissionError {
1598    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1599        f.write_str(COMPACT_QUERY_DIAGNOSTIC_MESSAGE)
1600    }
1601}
1602
1603impl std::error::Error for SchemaDdlAdmissionError {}
1604
1605impl fmt::Debug for ErrorDetail {
1606    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1607        fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
1608    }
1609}
1610
1611impl fmt::Debug for StoreError {
1612    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1613        fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
1614    }
1615}
1616
1617impl fmt::Debug for QueryErrorDetail {
1618    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1619        fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
1620    }
1621}
1622
1623impl fmt::Debug for RecoveryErrorDetail {
1624    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1625        fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
1626    }
1627}
1628
1629impl fmt::Debug for RecoveryFormatMarkerError {
1630    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1631        fmt_compact_diagnostic(
1632            f,
1633            diagnostic_code::DiagnosticCode::RuntimeCorruption,
1634            Some(diagnostic_code::DiagnosticDetail::RuntimeKind {
1635                kind: diagnostic_code::RuntimeErrorKind::Corruption,
1636            }),
1637        )
1638    }
1639}
1640
1641impl fmt::Debug for SchemaDdlAdmissionError {
1642    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1643        fmt_compact_diagnostic(
1644            f,
1645            diagnostic_code::DiagnosticCode::SchemaDdlAdmission,
1646            Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
1647                reason: self.diagnostic_code(),
1648            }),
1649        )
1650    }
1651}
1652
1653fn fmt_compact_diagnostic(
1654    f: &mut fmt::Formatter<'_>,
1655    code: diagnostic_code::DiagnosticCode,
1656    detail: Option<diagnostic_code::DiagnosticDetail>,
1657) -> fmt::Result {
1658    write!(
1659        f,
1660        "{}",
1661        diagnostic_code::ErrorCode::from_parts(code, detail).raw()
1662    )
1663}
1664
1665impl ErrorDetail {
1666    /// Return the compact diagnostic code for this structured detail.
1667    #[must_use]
1668    pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
1669        match self {
1670            Self::Store(error) => error.diagnostic_code(),
1671            Self::Query(error) => error.diagnostic_code(),
1672            Self::Recovery(error) => error.diagnostic_code(),
1673        }
1674    }
1675
1676    /// Return compact structured diagnostic detail when the payload carries one.
1677    #[must_use]
1678    pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
1679        match self {
1680            Self::Store(error) => error.diagnostic_detail(),
1681            Self::Query(error) => error.diagnostic_detail(),
1682            Self::Recovery(error) => error.diagnostic_detail(),
1683        }
1684    }
1685}
1686
1687impl RecoveryErrorDetail {
1688    /// Return the compact diagnostic code for this recovery detail.
1689    #[must_use]
1690    pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
1691        match self {
1692            Self::UnsupportedFormatVersion { .. } => {
1693                diagnostic_code::DiagnosticCode::RuntimeIncompatiblePersistedFormat
1694            }
1695            Self::MalformedFormatMarker { .. } => {
1696                diagnostic_code::DiagnosticCode::RuntimeCorruption
1697            }
1698        }
1699    }
1700
1701    /// Return compact structured diagnostic detail for this recovery detail.
1702    #[must_use]
1703    pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
1704        let kind = match self {
1705            Self::UnsupportedFormatVersion { .. } => {
1706                diagnostic_code::RuntimeErrorKind::IncompatiblePersistedFormat
1707            }
1708            Self::MalformedFormatMarker { .. } => diagnostic_code::RuntimeErrorKind::Corruption,
1709        };
1710
1711        Some(diagnostic_code::DiagnosticDetail::RuntimeKind { kind })
1712    }
1713}
1714
1715impl StoreError {
1716    /// Return the compact diagnostic code for this store detail.
1717    #[must_use]
1718    pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
1719        match self {
1720            Self::NotFound => diagnostic_code::DiagnosticCode::StoreNotFound,
1721            Self::Corrupt => diagnostic_code::DiagnosticCode::StoreCorruption,
1722            Self::InvariantViolation => diagnostic_code::DiagnosticCode::StoreInvariantViolation,
1723            Self::SchemaDdlPublicationRaceLost | Self::SchemaDdlSetNotNullValidationFailed => {
1724                diagnostic_code::DiagnosticCode::SchemaDdlAdmission
1725            }
1726        }
1727    }
1728
1729    /// Return compact structured diagnostic detail when the store error has one.
1730    #[must_use]
1731    pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
1732        match self {
1733            Self::SchemaDdlPublicationRaceLost => {
1734                Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
1735                    reason: diagnostic_code::SchemaDdlAdmissionCode::PublicationRaceLost,
1736                })
1737            }
1738            Self::SchemaDdlSetNotNullValidationFailed => {
1739                Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
1740                    reason: diagnostic_code::SchemaDdlAdmissionCode::SetNotNullValidationFailed,
1741                })
1742            }
1743            Self::NotFound | Self::Corrupt | Self::InvariantViolation => None,
1744        }
1745    }
1746}
1747
1748impl QueryErrorDetail {
1749    /// Return the compact diagnostic code for this query detail.
1750    #[must_use]
1751    pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
1752        match self {
1753            Self::NumericOverflow => diagnostic_code::DiagnosticCode::QueryNumericOverflow,
1754            Self::NumericNotRepresentable => {
1755                diagnostic_code::DiagnosticCode::QueryNumericNotRepresentable
1756            }
1757            Self::UnsupportedSqlFeature { .. } => {
1758                diagnostic_code::DiagnosticCode::QueryUnsupportedSqlFeature
1759            }
1760            Self::SqlLowering { .. } => diagnostic_code::DiagnosticCode::QueryUnsupportedSqlFeature,
1761            Self::UnsupportedProjection { .. } => {
1762                diagnostic_code::DiagnosticCode::QueryUnsupportedProjection
1763            }
1764            Self::UnknownAggregateTargetField => {
1765                diagnostic_code::DiagnosticCode::QueryUnknownAggregateTargetField
1766            }
1767            Self::ResultShapeMismatch { .. } => {
1768                diagnostic_code::DiagnosticCode::QueryResultShapeMismatch
1769            }
1770            Self::QueryReadAdmission { .. } => diagnostic_code::DiagnosticCode::QueryReadAdmission,
1771            Self::SqlSurfaceMismatch { .. } => {
1772                diagnostic_code::DiagnosticCode::QuerySqlSurfaceMismatch
1773            }
1774            Self::SqlWriteBoundary { .. } => diagnostic_code::DiagnosticCode::QuerySqlWriteBoundary,
1775            Self::SchemaDdlAdmission { .. } => diagnostic_code::DiagnosticCode::SchemaDdlAdmission,
1776            Self::StaleSchemaRevision => diagnostic_code::DiagnosticCode::RuntimeConflict,
1777        }
1778    }
1779
1780    /// Return compact structured diagnostic detail when the query detail has one.
1781    #[must_use]
1782    pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
1783        match self {
1784            Self::UnsupportedSqlFeature { feature } => {
1785                Some(diagnostic_code::DiagnosticDetail::UnsupportedSqlFeature { feature: *feature })
1786            }
1787            Self::SqlLowering { reason } => {
1788                Some(diagnostic_code::DiagnosticDetail::SqlLowering { reason: *reason })
1789            }
1790            Self::UnsupportedProjection { reason } => {
1791                Some(diagnostic_code::DiagnosticDetail::QueryProjection { reason: *reason })
1792            }
1793            Self::ResultShapeMismatch { reason } => {
1794                Some(diagnostic_code::DiagnosticDetail::QueryResultShape { reason: *reason })
1795            }
1796            Self::QueryReadAdmission { reason } => {
1797                Some(diagnostic_code::DiagnosticDetail::QueryReadAdmission { reason: *reason })
1798            }
1799            Self::SqlSurfaceMismatch { mismatch } => {
1800                Some(diagnostic_code::DiagnosticDetail::SqlSurfaceMismatch {
1801                    mismatch: *mismatch,
1802                })
1803            }
1804            Self::SqlWriteBoundary { boundary } => {
1805                Some(diagnostic_code::DiagnosticDetail::SqlWriteBoundary {
1806                    boundary: *boundary,
1807                })
1808            }
1809            Self::SchemaDdlAdmission { error } => {
1810                Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
1811                    reason: error.diagnostic_code(),
1812                })
1813            }
1814            Self::NumericOverflow
1815            | Self::NumericNotRepresentable
1816            | Self::UnknownAggregateTargetField
1817            | Self::StaleSchemaRevision => None,
1818        }
1819    }
1820}
1821
1822impl SchemaDdlAdmissionError {
1823    /// Return the compact diagnostic code for this SQL DDL admission reason.
1824    #[must_use]
1825    pub const fn diagnostic_code(&self) -> diagnostic_code::SchemaDdlAdmissionCode {
1826        match self {
1827            Self::MissingExpectedSchemaVersion => {
1828                diagnostic_code::SchemaDdlAdmissionCode::MissingExpectedSchemaVersion
1829            }
1830            Self::MissingNextSchemaVersion => {
1831                diagnostic_code::SchemaDdlAdmissionCode::MissingNextSchemaVersion
1832            }
1833            Self::StaleExpectedSchemaVersion => {
1834                diagnostic_code::SchemaDdlAdmissionCode::StaleExpectedSchemaVersion
1835            }
1836            Self::InvalidExpectedSchemaVersion => {
1837                diagnostic_code::SchemaDdlAdmissionCode::InvalidExpectedSchemaVersion
1838            }
1839            Self::InvalidNextSchemaVersion => {
1840                diagnostic_code::SchemaDdlAdmissionCode::InvalidNextSchemaVersion
1841            }
1842            Self::AcceptedSchemaChangeWithoutVersionBump => {
1843                diagnostic_code::SchemaDdlAdmissionCode::AcceptedSchemaChangeWithoutVersionBump
1844            }
1845            Self::EmptyVersionBump => diagnostic_code::SchemaDdlAdmissionCode::EmptyVersionBump,
1846            Self::VersionGap => diagnostic_code::SchemaDdlAdmissionCode::VersionGap,
1847            Self::VersionRollback => diagnostic_code::SchemaDdlAdmissionCode::VersionRollback,
1848            Self::FingerprintMethodMismatch => {
1849                diagnostic_code::SchemaDdlAdmissionCode::FingerprintMethodMismatch
1850            }
1851            Self::UnsupportedTransitionClass => {
1852                diagnostic_code::SchemaDdlAdmissionCode::UnsupportedTransitionClass
1853            }
1854            Self::PhysicalRunnerMissing => {
1855                diagnostic_code::SchemaDdlAdmissionCode::PhysicalRunnerMissing
1856            }
1857            Self::ValidationFailed => diagnostic_code::SchemaDdlAdmissionCode::ValidationFailed,
1858            Self::PublicationRaceLost => {
1859                diagnostic_code::SchemaDdlAdmissionCode::PublicationRaceLost
1860            }
1861            Self::InvalidAddColumnDefault => {
1862                diagnostic_code::SchemaDdlAdmissionCode::InvalidAddColumnDefault
1863            }
1864            Self::InvalidAlterColumnDefault => {
1865                diagnostic_code::SchemaDdlAdmissionCode::InvalidAlterColumnDefault
1866            }
1867            Self::GeneratedIndexDropRejected => {
1868                diagnostic_code::SchemaDdlAdmissionCode::GeneratedIndexDropRejected
1869            }
1870            Self::RequiredDropDefaultUnsupported => {
1871                diagnostic_code::SchemaDdlAdmissionCode::RequiredDropDefaultUnsupported
1872            }
1873            Self::GeneratedFieldDefaultChangeRejected => {
1874                diagnostic_code::SchemaDdlAdmissionCode::GeneratedFieldDefaultChangeRejected
1875            }
1876            Self::GeneratedFieldNullabilityChangeRejected => {
1877                diagnostic_code::SchemaDdlAdmissionCode::GeneratedFieldNullabilityChangeRejected
1878            }
1879            Self::SetNotNullValidationFailed => {
1880                diagnostic_code::SchemaDdlAdmissionCode::SetNotNullValidationFailed
1881            }
1882        }
1883    }
1884}
1885
1886///
1887/// ErrorClass
1888/// Internal error taxonomy for runtime classification.
1889/// Not a stable API; may change without notice.
1890///
1891
1892#[repr(u16)]
1893#[derive(Clone, Copy, Eq, PartialEq)]
1894pub enum ErrorClass {
1895    Corruption,
1896    IncompatiblePersistedFormat,
1897    NotFound,
1898    Internal,
1899    Conflict,
1900    Unsupported,
1901    InvariantViolation,
1902}
1903
1904impl ErrorClass {
1905    /// Return a compact diagnostic code for this broad class and origin pair.
1906    #[must_use]
1907    pub const fn diagnostic_code(self, origin: ErrorOrigin) -> diagnostic_code::DiagnosticCode {
1908        match self {
1909            Self::Corruption if matches!(origin, ErrorOrigin::Store) => {
1910                diagnostic_code::DiagnosticCode::StoreCorruption
1911            }
1912            Self::Corruption => diagnostic_code::DiagnosticCode::RuntimeCorruption,
1913            Self::IncompatiblePersistedFormat => {
1914                diagnostic_code::DiagnosticCode::RuntimeIncompatiblePersistedFormat
1915            }
1916            Self::NotFound if matches!(origin, ErrorOrigin::Store) => {
1917                diagnostic_code::DiagnosticCode::StoreNotFound
1918            }
1919            Self::NotFound => diagnostic_code::DiagnosticCode::RuntimeNotFound,
1920            Self::Internal => diagnostic_code::DiagnosticCode::RuntimeInternal,
1921            Self::Conflict => diagnostic_code::DiagnosticCode::RuntimeConflict,
1922            Self::Unsupported => diagnostic_code::DiagnosticCode::RuntimeUnsupported,
1923            Self::InvariantViolation if matches!(origin, ErrorOrigin::Store) => {
1924                diagnostic_code::DiagnosticCode::StoreInvariantViolation
1925            }
1926            Self::InvariantViolation => diagnostic_code::DiagnosticCode::RuntimeInvariantViolation,
1927        }
1928    }
1929}
1930
1931impl fmt::Debug for ErrorClass {
1932    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1933        write!(f, "{}", *self as u16)
1934    }
1935}
1936
1937///
1938/// ErrorOrigin
1939/// Internal origin taxonomy for runtime classification.
1940/// Not a stable API; may change without notice.
1941///
1942
1943#[repr(u16)]
1944#[derive(Clone, Copy, Eq, PartialEq)]
1945pub enum ErrorOrigin {
1946    Serialize,
1947    Store,
1948    Index,
1949    Identity,
1950    Query,
1951    Planner,
1952    Cursor,
1953    Recovery,
1954    Response,
1955    Executor,
1956    Interface,
1957}
1958
1959impl ErrorOrigin {
1960    /// Return the compact diagnostic origin for this internal origin.
1961    #[must_use]
1962    pub const fn diagnostic_origin(self) -> diagnostic_code::ErrorOrigin {
1963        match self {
1964            Self::Serialize => diagnostic_code::ErrorOrigin::Serialize,
1965            Self::Store => diagnostic_code::ErrorOrigin::Store,
1966            Self::Index => diagnostic_code::ErrorOrigin::Index,
1967            Self::Identity => diagnostic_code::ErrorOrigin::Identity,
1968            Self::Query => diagnostic_code::ErrorOrigin::Query,
1969            Self::Planner => diagnostic_code::ErrorOrigin::Planner,
1970            Self::Cursor => diagnostic_code::ErrorOrigin::Cursor,
1971            Self::Recovery => diagnostic_code::ErrorOrigin::Recovery,
1972            Self::Response => diagnostic_code::ErrorOrigin::Response,
1973            Self::Executor => diagnostic_code::ErrorOrigin::Executor,
1974            Self::Interface => diagnostic_code::ErrorOrigin::Interface,
1975        }
1976    }
1977}
1978
1979impl fmt::Debug for ErrorOrigin {
1980    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1981        write!(f, "{}", *self as u16)
1982    }
1983}