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 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// ============================================================================
40// INTERNAL ERROR TAXONOMY — ARCHITECTURAL CONTRACT
41// ============================================================================
42//
43// This file defines the canonical runtime error classification system for
44// icydb-core. It is the single source of truth for:
45//
46//   • ErrorClass   (semantic domain)
47//   • ErrorOrigin  (subsystem boundary)
48//   • Structured detail payloads
49//   • Canonical constructor entry points
50//
51// -----------------------------------------------------------------------------
52// DESIGN INTENT
53// -----------------------------------------------------------------------------
54//
55// 1. InternalError is a *taxonomy carrier*, not a formatting utility.
56//
57//    - ErrorClass represents semantic meaning (corruption, invariant_violation,
58//      unsupported, etc).
59//    - ErrorOrigin represents the subsystem boundary (store, index, query,
60//      executor, serialize, interface, etc).
61//    - The (class, origin) pair must remain stable and intentional.
62//
63// 2. Call sites MUST prefer canonical constructors.
64//
65//    Do NOT construct errors manually via:
66//        InternalError::new(class, origin)
67//    unless you are defining a new canonical helper here.
68//
69//    If a pattern appears more than once, centralize it here.
70//
71// 3. Constructors in this file must represent real architectural boundaries.
72//
73//    Add a new helper ONLY if it:
74//
75//      • Encodes a cross-cutting invariant,
76//      • Represents a subsystem boundary,
77//      • Or prevents taxonomy drift across call sites.
78//
79//    Do NOT add feature-specific helpers.
80//    Do NOT add one-off formatting helpers.
81//    Do NOT turn this file into a generic message factory.
82//
83// 4. ErrorDetail must align with ErrorOrigin.
84//
85//    If detail is present, it MUST correspond to the origin.
86//    Do not attach mismatched detail variants.
87//
88// 5. Plan-layer errors are NOT runtime failures.
89//
90//    PlanError and CursorPlanError must be translated into
91//    executor/query invariants via the canonical mapping functions.
92//    Do not leak plan-layer error types across execution boundaries.
93//
94// 6. Preserve taxonomy stability.
95//
96//    Do NOT:
97//      • Merge error classes.
98//      • Reclassify corruption as internal.
99//      • Downgrade invariant violations.
100//      • Introduce ambiguous class/origin combinations.
101//
102//    Any change to ErrorClass or ErrorOrigin is an architectural change
103//    and must be reviewed accordingly.
104//
105// -----------------------------------------------------------------------------
106// NON-GOALS
107// -----------------------------------------------------------------------------
108//
109// This is NOT:
110//
111//   • A public API contract.
112//   • A generic error abstraction layer.
113//   • A feature-specific message builder.
114//   • A dumping ground for temporary error conversions.
115//
116// -----------------------------------------------------------------------------
117// MAINTENANCE GUIDELINES
118// -----------------------------------------------------------------------------
119//
120// When modifying this file:
121//
122//   1. Ensure classification semantics remain consistent.
123//   2. Avoid constructor proliferation.
124//   3. Prefer narrow, origin-specific helpers over ad-hoc new(...).
125//   4. Keep formatting minimal and standardized.
126//   5. Keep this file boring and stable.
127//
128// If this file grows rapidly, something is wrong at the call sites.
129//
130// ============================================================================
131
132/// Safe accepted mutation identity retained only when constructing a failure.
133#[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    /// Bind one mutation failure to its accepted entity, operation, and input.
142    #[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    /// Bind a failure to an operation before any concrete input row is selected.
156    #[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
214/// Numeric context retained behind one thin error-only allocation.
215pub struct DiagnosticFactDetail {
216    diagnostic: diagnostic_code::Diagnostic,
217    facts: Vec<(diagnostic_code::DiagnosticFactTag, u64)>,
218}
219
220///
221/// InternalError
222///
223/// Structured runtime error with a stable internal classification.
224/// Not a stable API; intended for internal use and may change without notice.
225///
226
227pub struct InternalError {
228    pub(crate) class: ErrorClass,
229    pub(crate) origin: ErrorOrigin,
230
231    /// Optional structured error detail.
232    /// The variant (if present) must correspond to `origin`.
233    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    /// Construct an InternalError with optional origin-specific detail.
242    /// This constructor provides default StoreError details for certain
243    /// (class, origin) combinations but does not guarantee a detail payload.
244    #[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    /// Return the internal error class taxonomy.
266    #[must_use]
267    pub const fn class(&self) -> ErrorClass {
268        self.class
269    }
270
271    /// Return the internal error origin taxonomy.
272    #[must_use]
273    pub const fn origin(&self) -> ErrorOrigin {
274        self.origin
275    }
276
277    /// Return the rendered internal error message.
278    #[must_use]
279    pub const fn message(&self) -> &'static str {
280        compact_message_for(self.class, self.origin)
281    }
282
283    /// Return the optional structured detail payload.
284    #[must_use]
285    pub const fn detail(&self) -> Option<&ErrorDetail> {
286        self.detail.as_ref()
287    }
288
289    /// Return compact diagnostic identity for this internal error.
290    #[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    /// Project typed internal context into canonical public numeric facts.
302    #[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    /// Return the compact diagnostic code for this internal error.
312    #[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    /// Consume and return the rendered internal error message.
321    #[must_use]
322    pub fn into_message(self) -> String {
323        self.message().to_string()
324    }
325
326    /// Construct an error while preserving an explicit class/origin taxonomy pair.
327    #[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    /// Construct a query-boundary error for a named entity absent from accepted schema authority.
393    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    /// Construct an executor-origin hard execution-budget rejection.
405    #[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    /// Construct an executor-origin rejection for one indivisible page unit.
445    #[cold]
446    #[inline(never)]
447    pub(crate) fn page_unit_too_large(
448        resource: diagnostic_code::DiagnosticExecutionBudgetResource,
449        limit: u64,
450        attempted: u64,
451    ) -> Self {
452        Self::with_diagnostic_facts(
453            ErrorClass::Unsupported,
454            ErrorOrigin::Executor,
455            Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
456                boundary: diagnostic_code::RuntimeBoundaryCode::PageUnitTooLarge,
457            }),
458            vec![
459                (
460                    diagnostic_code::DiagnosticFactTag::BudgetResource,
461                    resource.raw(),
462                ),
463                (diagnostic_code::DiagnosticFactTag::Limit, limit),
464                (diagnostic_code::DiagnosticFactTag::Actual, attempted),
465            ],
466        )
467    }
468
469    /// Rebuild this error with a new origin while preserving class taxonomy.
470    ///
471    /// Numeric facts are origin-independent and remain safe after recovery
472    /// relabeling. Other origin-scoped detail payloads are dropped.
473    #[cold]
474    #[inline(never)]
475    pub(crate) fn with_origin(self, origin: ErrorOrigin) -> Self {
476        match self.detail {
477            Some(ErrorDetail::DiagnosticFacts(detail)) => Self::with_diagnostic_facts(
478                self.class,
479                origin,
480                detail.diagnostic.detail().copied(),
481                detail.facts,
482            ),
483            _ => Self::classified(self.class, origin),
484        }
485    }
486
487    /// Construct an index-origin invariant violation.
488    #[cold]
489    #[inline(never)]
490    pub(crate) fn index_invariant() -> Self {
491        Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Index)
492    }
493
494    /// Construct the canonical index field-count invariant for key building.
495    pub(crate) fn index_key_field_count_exceeds_max(
496        entity_tag: u64,
497        physical_generation: u64,
498        field_count: usize,
499        max_fields: usize,
500    ) -> Self {
501        Self::with_diagnostic_facts(
502            ErrorClass::InvariantViolation,
503            ErrorOrigin::Index,
504            None,
505            vec![
506                (diagnostic_code::DiagnosticFactTag::EntityTag, entity_tag),
507                (
508                    diagnostic_code::DiagnosticFactTag::PhysicalGeneration,
509                    physical_generation,
510                ),
511                (
512                    diagnostic_code::DiagnosticFactTag::ComponentKind,
513                    diagnostic_code::DiagnosticComponentKind::IndexKey.raw(),
514                ),
515                (
516                    diagnostic_code::DiagnosticFactTag::ActualArity,
517                    field_count as u64,
518                ),
519                (
520                    diagnostic_code::DiagnosticFactTag::Maximum,
521                    max_fields as u64,
522                ),
523            ],
524        )
525    }
526
527    /// Construct the canonical index-expression source-type mismatch invariant.
528    pub(crate) fn index_expression_source_type_mismatch(
529        _index_name: &str,
530        _expression: impl Sized,
531        _expected: impl Sized,
532        _source_label: &str,
533    ) -> Self {
534        Self::index_invariant()
535    }
536
537    /// Construct a planner-origin invariant violation for executor-boundary
538    /// contract drift.
539    #[cold]
540    #[inline(never)]
541    pub(crate) fn planner_executor_invariant() -> Self {
542        Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Planner)
543    }
544
545    /// Construct a query-origin invariant violation for executor-boundary
546    /// contract drift.
547    #[cold]
548    #[inline(never)]
549    pub(crate) fn query_executor_invariant() -> Self {
550        Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Query)
551    }
552
553    /// Construct a cursor-origin invariant violation for executor-boundary
554    /// contract drift.
555    #[cold]
556    #[inline(never)]
557    pub(crate) fn cursor_executor_invariant() -> Self {
558        Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Cursor)
559    }
560
561    /// Construct an executor-origin invariant violation.
562    #[cold]
563    #[inline(never)]
564    pub(crate) fn executor_invariant() -> Self {
565        Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Executor)
566    }
567
568    /// Construct an executor-origin internal error.
569    #[cold]
570    #[inline(never)]
571    pub(crate) fn executor_internal() -> Self {
572        Self::new(ErrorClass::Internal, ErrorOrigin::Executor)
573    }
574
575    /// Construct an executor-origin unsupported error.
576    #[cold]
577    #[inline(never)]
578    pub(crate) fn executor_unsupported() -> Self {
579        Self::new(ErrorClass::Unsupported, ErrorOrigin::Executor)
580    }
581
582    /// Construct an executor-origin database-owned-field authorship rejection.
583    #[cold]
584    #[inline(never)]
585    pub(crate) fn mutation_database_owned_field_explicit(
586        context: MutationDiagnosticContext,
587        field_id: u32,
588    ) -> Self {
589        Self::mutation_boundary_with_facts(
590            ErrorClass::Unsupported,
591            diagnostic_code::RuntimeBoundaryCode::MutationDatabaseOwnedFieldExplicit,
592            context.facts(Some(field_id)),
593        )
594    }
595
596    /// Construct an executor-origin required-field omission rejection.
597    #[must_use]
598    #[cold]
599    #[inline(never)]
600    pub(crate) fn mutation_required_field_missing(
601        context: MutationDiagnosticContext,
602        field_id: u32,
603    ) -> Self {
604        Self::mutation_boundary_with_facts(
605            ErrorClass::Unsupported,
606            diagnostic_code::RuntimeBoundaryCode::MutationRequiredFieldMissing,
607            context.facts(Some(field_id)),
608        )
609    }
610
611    /// Construct an executor-origin managed-timestamp clock regression.
612    #[must_use]
613    #[cold]
614    #[inline(never)]
615    pub(crate) fn mutation_managed_timestamp_regression(
616        context: MutationDiagnosticContext,
617    ) -> Self {
618        Self::mutation_boundary_with_facts(
619            ErrorClass::InvariantViolation,
620            diagnostic_code::RuntimeBoundaryCode::MutationManagedTimestampRegression,
621            context.facts(None),
622        )
623    }
624
625    /// Construct an executor-origin accepted constraint or activation-gate violation.
626    pub(crate) fn mutation_constraint_violation(context: AcceptedConstraintFactContext) -> Self {
627        Self::mutation_boundary_with_facts(
628            ErrorClass::InvariantViolation,
629            diagnostic_code::RuntimeBoundaryCode::ConstraintViolation,
630            context.facts(),
631        )
632    }
633
634    /// Construct an executor-origin corruption failure for row-constraint authority.
635    pub(crate) fn accepted_row_constraint_program_corrupt() -> Self {
636        Self {
637            class: ErrorClass::Corruption,
638            origin: ErrorOrigin::Executor,
639            detail: Some(ErrorDetail::Executor(
640                ExecutorErrorDetail::AcceptedRowConstraintProgramCorrupt,
641            )),
642        }
643    }
644
645    /// Construct one typed migration conflict for an incomplete activation gate.
646    pub(crate) fn mutation_constraint_activation_write_blocked(
647        context: AcceptedConstraintFactContext,
648    ) -> Self {
649        Self::mutation_boundary_with_facts(
650            ErrorClass::Conflict,
651            diagnostic_code::RuntimeBoundaryCode::ConstraintActivationWriteBlocked,
652            context.facts(),
653        )
654    }
655
656    /// Construct an executor-origin mutation unknown-field invariant.
657    pub(crate) fn mutation_structural_field_unknown(_entity_path: &str, _field_name: &str) -> Self {
658        Self::executor_invariant()
659    }
660
661    /// Construct a query-origin scalar page invariant for missing order at the cursor boundary.
662    pub(crate) fn scalar_page_cursor_boundary_order_required() -> Self {
663        Self::query_executor_invariant()
664    }
665
666    /// Construct a query-origin scalar page invariant for cursor-before-ordering drift.
667    pub(crate) fn scalar_page_cursor_boundary_after_ordering_required() -> Self {
668        Self::query_executor_invariant()
669    }
670
671    /// Construct a query-origin scalar page invariant for pagination-before-ordering drift.
672    pub(crate) fn scalar_page_pagination_after_ordering_required() -> Self {
673        Self::query_executor_invariant()
674    }
675
676    /// Construct a query-origin fast-stream invariant for route kind/request mismatch.
677    pub(crate) fn fast_stream_route_kind_request_match_required() -> Self {
678        Self::query_executor_invariant()
679    }
680
681    /// Construct a query-origin scan invariant for missing index-prefix executable specs.
682    pub(crate) fn secondary_index_prefix_spec_required() -> Self {
683        Self::query_executor_invariant()
684    }
685
686    /// Construct a query-origin scan invariant for missing index-range executable specs.
687    pub(crate) fn index_range_limit_spec_required() -> Self {
688        Self::query_executor_invariant()
689    }
690
691    /// Construct an executor-origin mutation conflict for duplicate atomic save keys.
692    #[cold]
693    #[inline(never)]
694    pub(crate) fn mutation_atomic_save_duplicate_key(
695        entity_tag: u64,
696        first_position: u32,
697        duplicate_position: u32,
698    ) -> Self {
699        Self::mutation_boundary_with_facts(
700            ErrorClass::Conflict,
701            diagnostic_code::RuntimeBoundaryCode::MutationBatchDuplicateKey,
702            vec![
703                (diagnostic_code::DiagnosticFactTag::EntityTag, entity_tag),
704                (
705                    diagnostic_code::DiagnosticFactTag::FirstBatchPosition,
706                    u64::from(first_position),
707                ),
708                (
709                    diagnostic_code::DiagnosticFactTag::DuplicateBatchPosition,
710                    u64::from(duplicate_position),
711                ),
712            ],
713        )
714    }
715
716    /// Construct an executor-origin empty mixed-mutation batch rejection.
717    #[cold]
718    #[inline(never)]
719    pub(crate) fn mutation_batch_empty() -> Self {
720        Self::mutation_boundary_with_facts(
721            ErrorClass::Unsupported,
722            diagnostic_code::RuntimeBoundaryCode::MutationBatchEmpty,
723            vec![(diagnostic_code::DiagnosticFactTag::ActualCount, 0)],
724        )
725    }
726
727    /// Construct an executor-origin mixed-mutation item-bound rejection.
728    #[cold]
729    #[inline(never)]
730    pub(crate) fn mutation_batch_too_many_items(actual_count: usize, limit: usize) -> Self {
731        Self::mutation_boundary_with_facts(
732            ErrorClass::Unsupported,
733            diagnostic_code::RuntimeBoundaryCode::MutationBatchTooManyItems,
734            vec![
735                (
736                    diagnostic_code::DiagnosticFactTag::ActualCount,
737                    actual_count as u64,
738                ),
739                (diagnostic_code::DiagnosticFactTag::Limit, limit as u64),
740            ],
741        )
742    }
743
744    /// Construct an executor-origin mixed-mutation staged-byte-bound rejection.
745    #[cold]
746    #[inline(never)]
747    pub(crate) fn mutation_batch_staged_bytes_exceeded(
748        actual_bytes: Option<usize>,
749        limit: usize,
750    ) -> Self {
751        let mut facts = Vec::with_capacity(1 + usize::from(actual_bytes.is_some()));
752        if let Some(actual_bytes) = actual_bytes {
753            facts.push((
754                diagnostic_code::DiagnosticFactTag::ActualLength,
755                actual_bytes as u64,
756            ));
757        }
758        facts.push((diagnostic_code::DiagnosticFactTag::Limit, limit as u64));
759        Self::mutation_boundary_with_facts(
760            ErrorClass::Unsupported,
761            diagnostic_code::RuntimeBoundaryCode::MutationBatchStagedBytesExceeded,
762            facts,
763        )
764    }
765
766    /// Construct an executor-origin mixed-mutation result-byte-bound rejection.
767    #[cold]
768    #[inline(never)]
769    pub(crate) fn mutation_batch_result_bytes_exceeded(actual_bytes: usize, limit: usize) -> Self {
770        Self::mutation_boundary_with_facts(
771            ErrorClass::Unsupported,
772            diagnostic_code::RuntimeBoundaryCode::MutationBatchResultBytesExceeded,
773            vec![
774                (
775                    diagnostic_code::DiagnosticFactTag::ActualLength,
776                    actual_bytes as u64,
777                ),
778                (diagnostic_code::DiagnosticFactTag::Limit, limit as u64),
779            ],
780        )
781    }
782
783    /// Construct an executor-origin prepared-commit work-bound rejection.
784    #[cold]
785    #[inline(never)]
786    pub(crate) fn mutation_batch_commit_work_exceeded(
787        actual_units: Option<usize>,
788        limit: usize,
789    ) -> Self {
790        let mut facts = Vec::with_capacity(1 + usize::from(actual_units.is_some()));
791        if let Some(actual_units) = actual_units {
792            facts.push((
793                diagnostic_code::DiagnosticFactTag::ActualCount,
794                actual_units as u64,
795            ));
796        }
797        facts.push((diagnostic_code::DiagnosticFactTag::Limit, limit as u64));
798        Self::mutation_boundary_with_facts(
799            ErrorClass::Unsupported,
800            diagnostic_code::RuntimeBoundaryCode::MutationBatchCommitWorkExceeded,
801            facts,
802        )
803    }
804
805    /// Construct the retryable cumulative journal-backlog pressure boundary.
806    pub(crate) fn convergence_backlog_pressure(
807        resource: diagnostic_code::DiagnosticBacklogResource,
808        current: u64,
809        proposed: u64,
810        limit: u64,
811    ) -> Self {
812        Self::mutation_boundary_with_facts(
813            ErrorClass::Conflict,
814            diagnostic_code::RuntimeBoundaryCode::ConvergenceBacklogPressure,
815            vec![
816                (
817                    diagnostic_code::DiagnosticFactTag::BacklogResource,
818                    resource.raw(),
819                ),
820                (diagnostic_code::DiagnosticFactTag::CurrentCount, current),
821                (diagnostic_code::DiagnosticFactTag::ProposedCount, proposed),
822                (diagnostic_code::DiagnosticFactTag::Limit, limit),
823            ],
824        )
825    }
826
827    /// Construct a query-origin exact-key item-bound rejection.
828    #[cold]
829    #[inline(never)]
830    pub(crate) fn exact_key_batch_too_many_items(actual_count: usize, limit: usize) -> Self {
831        Self::exact_key_batch_boundary_with_facts(
832            diagnostic_code::RuntimeBoundaryCode::ExactKeyBatchTooManyItems,
833            vec![
834                (
835                    diagnostic_code::DiagnosticFactTag::ActualCount,
836                    actual_count as u64,
837                ),
838                (diagnostic_code::DiagnosticFactTag::Limit, limit as u64),
839            ],
840        )
841    }
842
843    /// Construct a query-origin exact-key input-byte rejection.
844    #[cold]
845    #[inline(never)]
846    pub(crate) fn exact_key_batch_input_bytes_exceeded(actual_bytes: usize, limit: usize) -> Self {
847        Self::exact_key_batch_bytes_exceeded(
848            diagnostic_code::RuntimeBoundaryCode::ExactKeyBatchInputBytesExceeded,
849            actual_bytes,
850            limit,
851        )
852    }
853
854    /// Construct a query-origin exact-key stored-row-byte rejection.
855    #[cold]
856    #[inline(never)]
857    pub(crate) fn exact_key_batch_stored_bytes_exceeded(actual_bytes: usize, limit: usize) -> Self {
858        Self::exact_key_batch_bytes_exceeded(
859            diagnostic_code::RuntimeBoundaryCode::ExactKeyBatchStoredBytesExceeded,
860            actual_bytes,
861            limit,
862        )
863    }
864
865    /// Construct a query-origin exact-key result-byte rejection.
866    #[cold]
867    #[inline(never)]
868    pub(crate) fn exact_key_batch_result_bytes_exceeded(actual_bytes: usize, limit: usize) -> Self {
869        Self::exact_key_batch_bytes_exceeded(
870            diagnostic_code::RuntimeBoundaryCode::ExactKeyBatchResultBytesExceeded,
871            actual_bytes,
872            limit,
873        )
874    }
875
876    #[cold]
877    #[inline(never)]
878    fn exact_key_batch_bytes_exceeded(
879        boundary: diagnostic_code::RuntimeBoundaryCode,
880        actual_bytes: usize,
881        limit: usize,
882    ) -> Self {
883        Self::exact_key_batch_boundary_with_facts(
884            boundary,
885            vec![
886                (
887                    diagnostic_code::DiagnosticFactTag::ActualLength,
888                    actual_bytes as u64,
889                ),
890                (diagnostic_code::DiagnosticFactTag::Limit, limit as u64),
891            ],
892        )
893    }
894
895    /// Construct an executor-origin mixed-entity batch rejection.
896    #[cold]
897    #[inline(never)]
898    pub(crate) fn mutation_batch_entity_mismatch(
899        batch_position: u32,
900        expected_entity_tag: u64,
901        actual_entity_tag: u64,
902    ) -> Self {
903        Self::mutation_boundary_with_facts(
904            ErrorClass::Conflict,
905            diagnostic_code::RuntimeBoundaryCode::MutationBatchEntityMismatch,
906            vec![
907                (
908                    diagnostic_code::DiagnosticFactTag::BatchPosition,
909                    u64::from(batch_position),
910                ),
911                (
912                    diagnostic_code::DiagnosticFactTag::ExpectedEntityTag,
913                    expected_entity_tag,
914                ),
915                (
916                    diagnostic_code::DiagnosticFactTag::ActualEntityTag,
917                    actual_entity_tag,
918                ),
919            ],
920        )
921    }
922
923    /// Construct an executor-origin mutation invariant for index-store generation drift.
924    pub(crate) fn mutation_index_store_generation_changed(
925        _expected_generation: u64,
926        _observed_generation: u64,
927    ) -> Self {
928        Self::executor_invariant()
929    }
930
931    /// Construct a planner-origin invariant violation.
932    #[cold]
933    #[inline(never)]
934    pub(crate) fn planner_invariant() -> Self {
935        Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Planner)
936    }
937
938    /// Construct a planner-origin invalid-logical-plan invariant.
939    pub(crate) fn query_invalid_logical_plan() -> Self {
940        Self::planner_invariant()
941    }
942
943    /// Construct a store-origin invariant violation.
944    pub(crate) fn store_invariant() -> Self {
945        Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Store)
946    }
947
948    /// Construct a store-origin internal error.
949    #[cold]
950    #[inline(never)]
951    pub(crate) fn store_internal() -> Self {
952        Self::new(ErrorClass::Internal, ErrorOrigin::Store)
953    }
954
955    /// Construct the canonical unconfigured commit-memory id internal error.
956    pub(crate) fn commit_memory_id_unconfigured() -> Self {
957        Self::store_internal()
958    }
959
960    /// Construct the canonical initialized commit-store lookup invariant.
961    pub(crate) fn commit_store_uninitialized() -> Self {
962        Self::store_invariant()
963    }
964
965    /// Construct the canonical commit-memory id mismatch internal error.
966    pub(crate) fn commit_memory_id_mismatch(cached_id: u8, configured_id: u8) -> Self {
967        Self::with_diagnostic_facts(
968            ErrorClass::Internal,
969            ErrorOrigin::Store,
970            None,
971            vec![
972                (
973                    diagnostic_code::DiagnosticFactTag::ExpectedMemoryId,
974                    u64::from(cached_id),
975                ),
976                (
977                    diagnostic_code::DiagnosticFactTag::ActualMemoryId,
978                    u64::from(configured_id),
979                ),
980            ],
981        )
982    }
983
984    /// Construct the canonical commit-memory stable-key mismatch internal error.
985    pub(crate) fn commit_memory_stable_key_mismatch(
986        _cached_key: &str,
987        _configured_key: &str,
988    ) -> Self {
989        Self::store_internal()
990    }
991
992    /// Construct the canonical database-incarnation generation failure.
993    pub(crate) fn database_incarnation_generation_failed() -> Self {
994        Self::store_internal()
995    }
996
997    /// Construct the canonical zero database-incarnation corruption error.
998    pub(crate) fn database_incarnation_invalid() -> Self {
999        Self::store_corruption()
1000    }
1001
1002    /// Construct a recovery-origin incompatible store-format error.
1003    pub(crate) fn recovery_unsupported_database_format(found: Option<u16>, required: u16) -> Self {
1004        Self {
1005            class: ErrorClass::IncompatiblePersistedFormat,
1006            origin: ErrorOrigin::Recovery,
1007            detail: Some(ErrorDetail::Recovery(
1008                RecoveryErrorDetail::UnsupportedFormatVersion { found, required },
1009            )),
1010        }
1011    }
1012
1013    /// Construct a recovery-origin malformed store-format marker error.
1014    pub(crate) fn recovery_malformed_database_format_marker(
1015        reason: RecoveryFormatMarkerError,
1016    ) -> Self {
1017        Self {
1018            class: ErrorClass::Corruption,
1019            origin: ErrorOrigin::Recovery,
1020            detail: Some(ErrorDetail::Recovery(
1021                RecoveryErrorDetail::MalformedFormatMarker { reason },
1022            )),
1023        }
1024    }
1025
1026    /// Construct a recovery-origin boot control-memory failure.
1027    pub(crate) fn recovery_database_format_control_unavailable() -> Self {
1028        Self::new(ErrorClass::Internal, ErrorOrigin::Recovery)
1029    }
1030
1031    /// Construct the retryable internal boundary returned while bounded startup recovery remains.
1032    pub(crate) fn recovery_pending() -> Self {
1033        Self::with_diagnostic_facts(
1034            ErrorClass::Conflict,
1035            ErrorOrigin::Recovery,
1036            Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
1037                boundary: diagnostic_code::RuntimeBoundaryCode::DatabaseStartupRecoveryPending,
1038            }),
1039            Vec::new(),
1040        )
1041    }
1042
1043    /// Construct fail-closed corruption for the bounded startup control cell.
1044    pub(crate) fn startup_control_corruption() -> Self {
1045        Self::new(ErrorClass::Corruption, ErrorOrigin::Recovery)
1046    }
1047
1048    /// Construct a commit control-memory growth failure.
1049    pub(crate) fn commit_control_memory_growth_failed() -> Self {
1050        Self::store_internal()
1051    }
1052
1053    /// Construct a store-format memory registration failure.
1054    #[cfg(not(test))]
1055    pub(crate) fn database_format_memory_registration_failed(_err: impl Sized) -> Self {
1056        Self::store_internal()
1057    }
1058
1059    /// Construct the canonical recovered-effect verification failure.
1060    pub(crate) fn recovery_effect_verification_failed() -> Self {
1061        Self::store_corruption()
1062    }
1063
1064    /// Construct an index-origin internal error.
1065    #[cold]
1066    #[inline(never)]
1067    pub(crate) fn index_internal() -> Self {
1068        Self::new(ErrorClass::Internal, ErrorOrigin::Index)
1069    }
1070
1071    /// Construct the canonical missing old entity-key internal error for structural index removal.
1072    pub(crate) fn structural_index_removal_entity_key_required() -> Self {
1073        Self::index_internal()
1074    }
1075
1076    /// Construct the canonical missing new entity-key internal error for structural index insertion.
1077    pub(crate) fn structural_index_insertion_entity_key_required() -> Self {
1078        Self::index_internal()
1079    }
1080
1081    /// Construct the canonical missing old entity-key internal error for index commit-op removal.
1082    pub(crate) fn index_commit_op_old_entity_key_required() -> Self {
1083        Self::index_internal()
1084    }
1085
1086    /// Construct the canonical missing new entity-key internal error for index commit-op insertion.
1087    pub(crate) fn index_commit_op_new_entity_key_required() -> Self {
1088        Self::index_internal()
1089    }
1090
1091    /// Construct a query-origin internal error.
1092    #[cfg(test)]
1093    pub(crate) fn query_internal() -> Self {
1094        Self::new(ErrorClass::Internal, ErrorOrigin::Query)
1095    }
1096
1097    /// Construct a query-origin unsupported error.
1098    #[cold]
1099    #[inline(never)]
1100    pub(crate) fn query_unsupported() -> Self {
1101        Self::new(ErrorClass::Unsupported, ErrorOrigin::Query)
1102    }
1103
1104    /// Construct a query-origin conflict for execution against a superseded
1105    /// accepted schema revision.
1106    #[cold]
1107    #[inline(never)]
1108    pub(crate) fn query_stale_accepted_schema_revision(
1109        expected_revision: u64,
1110        current_revision: Option<u64>,
1111    ) -> Self {
1112        let mut facts = Vec::with_capacity(1 + usize::from(current_revision.is_some()));
1113        facts.push((
1114            diagnostic_code::DiagnosticFactTag::ExpectedRevision,
1115            expected_revision,
1116        ));
1117        if let Some(current_revision) = current_revision {
1118            facts.push((
1119                diagnostic_code::DiagnosticFactTag::CurrentRevision,
1120                current_revision,
1121            ));
1122        }
1123        Self::with_diagnostic_facts(ErrorClass::Conflict, ErrorOrigin::Query, None, facts)
1124    }
1125
1126    /// Construct a query-origin SQL DDL admission error with structured detail.
1127    #[cold]
1128    #[inline(never)]
1129    #[cfg(feature = "sql")]
1130    pub(crate) fn query_schema_ddl_admission(error: SchemaDdlAdmissionError) -> Self {
1131        Self {
1132            class: ErrorClass::Unsupported,
1133            origin: ErrorOrigin::Query,
1134            detail: Some(ErrorDetail::Query(QueryErrorDetail::SchemaDdlAdmission {
1135                error,
1136            })),
1137        }
1138    }
1139
1140    /// Construct a query-origin numeric overflow error with structured detail.
1141    #[cold]
1142    #[inline(never)]
1143    pub(crate) fn query_numeric_overflow() -> Self {
1144        Self {
1145            class: ErrorClass::Unsupported,
1146            origin: ErrorOrigin::Query,
1147            detail: Some(ErrorDetail::Query(QueryErrorDetail::NumericOverflow)),
1148        }
1149    }
1150
1151    /// Construct a query-origin non-representable numeric result error with
1152    /// structured detail.
1153    #[cold]
1154    #[inline(never)]
1155    pub(crate) fn query_numeric_not_representable() -> Self {
1156        Self {
1157            class: ErrorClass::Unsupported,
1158            origin: ErrorOrigin::Query,
1159            detail: Some(ErrorDetail::Query(
1160                QueryErrorDetail::NumericNotRepresentable,
1161            )),
1162        }
1163    }
1164
1165    /// Construct a serialize-origin internal error.
1166    #[cold]
1167    #[inline(never)]
1168    pub(crate) fn serialize_internal() -> Self {
1169        Self::new(ErrorClass::Internal, ErrorOrigin::Serialize)
1170    }
1171
1172    /// Construct the canonical persisted-row encode internal error.
1173    pub(crate) fn persisted_row_encode_failed(_detail: impl Sized) -> Self {
1174        Self::persisted_row_encode_internal()
1175    }
1176
1177    /// Construct the compact persisted-row encode internal error.
1178    pub(crate) fn persisted_row_encode_internal() -> Self {
1179        Self::serialize_internal()
1180    }
1181
1182    /// Construct the compact persisted-row field encode internal error.
1183    pub(crate) fn persisted_row_field_encode_internal(_field_name: &str) -> Self {
1184        Self::persisted_row_encode_internal()
1185    }
1186
1187    /// Construct a store-origin corruption error.
1188    #[cold]
1189    #[inline(never)]
1190    pub(crate) fn store_corruption() -> Self {
1191        Self::new(ErrorClass::Corruption, ErrorOrigin::Store)
1192    }
1193
1194    /// Construct a store-origin commit-marker corruption error.
1195    pub(crate) fn commit_corruption() -> Self {
1196        Self::store_corruption()
1197    }
1198
1199    /// Construct a store-origin commit-marker component corruption error.
1200    pub(crate) fn commit_component_corruption() -> Self {
1201        Self::commit_corruption()
1202    }
1203
1204    /// Construct the canonical commit-marker id generation internal error.
1205    pub(crate) fn commit_id_generation_failed() -> Self {
1206        Self::store_internal()
1207    }
1208
1209    /// Construct the canonical commit-marker payload u32-length-limit error.
1210    pub(crate) fn commit_marker_payload_exceeds_u32_length_limit() -> Self {
1211        Self::store_unsupported()
1212    }
1213
1214    /// Construct the canonical commit-marker component invalid-length corruption error.
1215    pub(crate) fn commit_component_length_invalid(actual_length: usize, limit: usize) -> Self {
1216        Self::with_diagnostic_facts(
1217            ErrorClass::Corruption,
1218            ErrorOrigin::Store,
1219            None,
1220            vec![
1221                (
1222                    diagnostic_code::DiagnosticFactTag::ComponentKind,
1223                    diagnostic_code::DiagnosticComponentKind::CommitDataKey.raw(),
1224                ),
1225                (
1226                    diagnostic_code::DiagnosticFactTag::ActualLength,
1227                    actual_length as u64,
1228                ),
1229                (diagnostic_code::DiagnosticFactTag::Limit, limit as u64),
1230            ],
1231        )
1232    }
1233
1234    /// Construct the canonical commit-marker max-size corruption error.
1235    pub(crate) fn commit_marker_exceeds_max_size() -> Self {
1236        Self::commit_corruption()
1237    }
1238
1239    /// Construct the canonical commit-control slot max-size unsupported error.
1240    pub(crate) fn commit_control_slot_exceeds_max_size() -> Self {
1241        Self::store_unsupported()
1242    }
1243
1244    /// Construct the canonical commit-control marker-bytes length-limit error.
1245    pub(crate) fn commit_control_slot_marker_bytes_exceed_u32_length_limit() -> Self {
1246        Self::store_unsupported()
1247    }
1248
1249    /// Construct an index-origin corruption error.
1250    #[cold]
1251    #[inline(never)]
1252    pub(crate) fn index_corruption() -> Self {
1253        Self::new(ErrorClass::Corruption, ErrorOrigin::Index)
1254    }
1255
1256    /// Construct the canonical unique-validation corruption wrapper.
1257    pub(crate) fn index_unique_validation_corruption() -> Self {
1258        Self::index_plan_index_corruption()
1259    }
1260
1261    /// Construct the canonical structural index-entry corruption wrapper.
1262    pub(crate) fn structural_index_entry_corruption() -> Self {
1263        Self::index_plan_index_corruption()
1264    }
1265
1266    /// Construct the canonical missing new entity-key invariant during unique validation.
1267    pub(crate) fn index_unique_validation_entity_key_required() -> Self {
1268        Self::index_invariant()
1269    }
1270
1271    /// Construct the canonical unique-validation structural row-decode corruption error.
1272    pub(crate) fn index_unique_validation_row_deserialize_failed() -> Self {
1273        Self::index_plan_serialize_corruption()
1274    }
1275
1276    /// Construct the canonical unique-validation primary-key slot decode corruption error.
1277    pub(crate) fn index_unique_validation_primary_key_decode_failed() -> Self {
1278        Self::index_plan_serialize_corruption()
1279    }
1280
1281    /// Construct the canonical unique-validation stored key rebuild corruption error.
1282    pub(crate) fn index_unique_validation_key_rebuild_failed() -> Self {
1283        Self::index_plan_serialize_corruption()
1284    }
1285
1286    /// Construct the canonical unique-validation missing-row corruption error.
1287    pub(crate) fn index_unique_validation_row_required() -> Self {
1288        Self::index_plan_store_corruption()
1289    }
1290
1291    /// Construct the canonical index-only predicate missing-component invariant.
1292    pub(crate) fn index_only_predicate_component_required() -> Self {
1293        Self::index_invariant()
1294    }
1295
1296    /// Construct the canonical index-scan continuation-envelope invariant.
1297    pub(crate) fn index_scan_continuation_anchor_within_envelope_required() -> Self {
1298        Self::index_invariant()
1299    }
1300
1301    /// Construct the canonical index-scan continuation-advancement invariant.
1302    pub(crate) fn index_scan_continuation_advancement_required() -> Self {
1303        Self::index_invariant()
1304    }
1305
1306    /// Construct the canonical index-scan key-decode corruption error.
1307    pub(crate) fn index_scan_key_corrupted_during(
1308        _context: &'static str,
1309        _err: impl Sized,
1310    ) -> Self {
1311        Self::index_corruption()
1312    }
1313
1314    /// Construct the canonical index-scan missing projection-component invariant.
1315    pub(crate) fn index_projection_component_required(
1316        _index_name: &str,
1317        _component_index: usize,
1318    ) -> Self {
1319        Self::index_invariant()
1320    }
1321
1322    /// Construct the canonical scan-time index-entry decode corruption error.
1323    pub(crate) fn index_entry_decode_failed() -> Self {
1324        Self::index_corruption()
1325    }
1326
1327    /// Construct a serialize-origin corruption error.
1328    pub(crate) fn serialize_corruption() -> Self {
1329        Self::new(ErrorClass::Corruption, ErrorOrigin::Serialize)
1330    }
1331
1332    /// Construct the compact persisted-row decode corruption error.
1333    pub(crate) fn persisted_row_decode_corruption() -> Self {
1334        Self::serialize_corruption()
1335    }
1336
1337    /// Construct a persisted-row layout-window corruption error.
1338    pub(crate) fn persisted_row_layout_outside_accepted_window(
1339        row_layout: u32,
1340        history_floor: u32,
1341        current_layout: u32,
1342    ) -> Self {
1343        Self::with_diagnostic_facts(
1344            ErrorClass::Corruption,
1345            ErrorOrigin::Serialize,
1346            Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
1347                boundary:
1348                    diagnostic_code::RuntimeBoundaryCode::PersistedRowLayoutOutsideAcceptedWindow,
1349            }),
1350            vec![
1351                (
1352                    diagnostic_code::DiagnosticFactTag::RowLayout,
1353                    u64::from(row_layout),
1354                ),
1355                (
1356                    diagnostic_code::DiagnosticFactTag::HistoryFloor,
1357                    u64::from(history_floor),
1358                ),
1359                (
1360                    diagnostic_code::DiagnosticFactTag::CurrentLayout,
1361                    u64::from(current_layout),
1362                ),
1363            ],
1364        )
1365    }
1366
1367    /// Construct a persisted-row stamped-layout slot-count corruption error.
1368    pub(crate) fn persisted_row_slot_count_mismatch(
1369        row_layout: u32,
1370        expected_slot_count: usize,
1371        actual_slot_count: usize,
1372    ) -> Self {
1373        Self::with_diagnostic_facts(
1374            ErrorClass::Corruption,
1375            ErrorOrigin::Serialize,
1376            Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
1377                boundary: diagnostic_code::RuntimeBoundaryCode::PersistedRowSlotCountMismatch,
1378            }),
1379            vec![
1380                (
1381                    diagnostic_code::DiagnosticFactTag::RowLayout,
1382                    u64::from(row_layout),
1383                ),
1384                (
1385                    diagnostic_code::DiagnosticFactTag::ExpectedSlotCount,
1386                    expected_slot_count as u64,
1387                ),
1388                (
1389                    diagnostic_code::DiagnosticFactTag::ActualSlotCount,
1390                    actual_slot_count as u64,
1391                ),
1392            ],
1393        )
1394    }
1395
1396    /// Construct the canonical persisted-row field decode corruption error.
1397    pub(crate) fn persisted_row_field_decode_failed(field_name: &str, _detail: impl Sized) -> Self {
1398        Self::persisted_row_field_decode_corruption(field_name)
1399    }
1400
1401    /// Construct the compact persisted-row field decode corruption error.
1402    pub(crate) fn persisted_row_field_decode_corruption(_field_name: &str) -> Self {
1403        Self::persisted_row_decode_corruption()
1404    }
1405
1406    /// Construct the canonical persisted-row field-kind decode corruption error.
1407    pub(crate) fn persisted_row_field_kind_decode_failed(
1408        field_name: &str,
1409        _field_kind: impl fmt::Debug,
1410        _detail: impl Sized,
1411    ) -> Self {
1412        Self::persisted_row_field_decode_corruption(field_name)
1413    }
1414
1415    /// Construct the canonical persisted-row scalar-payload length corruption error.
1416    pub(crate) fn persisted_row_field_payload_exact_len_required(field_name: &str) -> Self {
1417        Self::persisted_row_field_decode_corruption(field_name)
1418    }
1419
1420    /// Construct the canonical persisted-row scalar-payload empty-body corruption error.
1421    pub(crate) fn persisted_row_field_payload_must_be_empty(field_name: &str) -> Self {
1422        Self::persisted_row_field_decode_corruption(field_name)
1423    }
1424
1425    /// Construct the canonical persisted-row scalar-payload invalid-byte corruption error.
1426    pub(crate) fn persisted_row_field_payload_invalid_byte(field_name: &str) -> Self {
1427        Self::persisted_row_field_decode_corruption(field_name)
1428    }
1429
1430    /// Construct the canonical persisted-row scalar-payload non-finite corruption error.
1431    pub(crate) fn persisted_row_field_payload_non_finite(field_name: &str) -> Self {
1432        Self::persisted_row_field_decode_corruption(field_name)
1433    }
1434
1435    /// Construct the canonical persisted-row invalid text payload corruption error.
1436    pub(crate) fn persisted_row_field_text_payload_invalid_utf8(field_name: &str) -> Self {
1437        Self::persisted_row_field_decode_corruption(field_name)
1438    }
1439
1440    /// Construct the canonical persisted-row structural slot-lookup invariant.
1441    pub(crate) fn persisted_row_slot_lookup_out_of_bounds(_model_path: &str, _slot: usize) -> Self {
1442        Self::index_invariant()
1443    }
1444
1445    /// Construct the canonical persisted-row structural slot-cache invariant.
1446    pub(crate) fn persisted_row_slot_cache_lookup_out_of_bounds(
1447        _model_path: &str,
1448        _slot: usize,
1449    ) -> Self {
1450        Self::index_invariant()
1451    }
1452
1453    /// Construct the canonical persisted-row primary-key decode corruption error.
1454    pub(crate) fn persisted_row_primary_key_not_primary_key_encodable(
1455        _data_key: impl fmt::Debug,
1456        _detail: impl Sized,
1457    ) -> Self {
1458        Self::persisted_row_decode_corruption()
1459    }
1460
1461    /// Construct the canonical persisted-row missing primary-key slot corruption error.
1462    pub(crate) fn persisted_row_primary_key_slot_missing(_data_key: impl fmt::Debug) -> Self {
1463        Self::persisted_row_decode_corruption()
1464    }
1465
1466    /// Construct the canonical persisted-row key mismatch corruption error.
1467    pub(crate) fn persisted_row_key_mismatch() -> Self {
1468        Self::store_corruption()
1469    }
1470
1471    /// Construct the canonical persisted-row missing declared-field corruption error.
1472    pub(crate) fn persisted_row_declared_field_missing(field_name: &str) -> Self {
1473        Self::persisted_row_field_decode_corruption(field_name)
1474    }
1475
1476    /// Construct the canonical reverse-index ordinal overflow internal error.
1477    pub(crate) fn reverse_index_ordinal_overflow(
1478        _source_path: &str,
1479        _field_name: &str,
1480        _target_path: &str,
1481        _detail: impl Sized,
1482    ) -> Self {
1483        Self::index_internal()
1484    }
1485
1486    /// Construct the canonical reverse-index entry corruption error.
1487    pub(crate) fn reverse_index_entry_corrupted(
1488        _source_path: &str,
1489        _field_name: &str,
1490        _target_path: &str,
1491        _index_key: impl fmt::Debug,
1492        _detail: impl Sized,
1493    ) -> Self {
1494        Self::index_corruption()
1495    }
1496
1497    /// Construct the canonical relation-target store missing internal error.
1498    pub(crate) fn relation_target_store_missing(
1499        _source_path: &str,
1500        _field_name: &str,
1501        _target_path: &str,
1502        _store_path: &str,
1503        _detail: impl Sized,
1504    ) -> Self {
1505        Self::executor_internal()
1506    }
1507
1508    /// Construct one accepted relation target primary-key arity mismatch.
1509    pub(crate) fn relation_target_primary_key_arity_mismatch(
1510        expected_arity: usize,
1511        actual_arity: usize,
1512    ) -> Self {
1513        Self::with_diagnostic_facts(
1514            ErrorClass::Internal,
1515            ErrorOrigin::Executor,
1516            None,
1517            vec![
1518                (
1519                    diagnostic_code::DiagnosticFactTag::ComponentKind,
1520                    diagnostic_code::DiagnosticComponentKind::RelationTargetPrimaryKey.raw(),
1521                ),
1522                (
1523                    diagnostic_code::DiagnosticFactTag::ExpectedArity,
1524                    expected_arity as u64,
1525                ),
1526                (
1527                    diagnostic_code::DiagnosticFactTag::ActualArity,
1528                    actual_arity as u64,
1529                ),
1530            ],
1531        )
1532    }
1533
1534    /// Construct the canonical relation-target key decode corruption error.
1535    pub(crate) fn relation_target_key_decode_failed(
1536        _context_label: &str,
1537        _source_path: &str,
1538        _field_name: &str,
1539        _target_path: &str,
1540        _detail: impl Sized,
1541    ) -> Self {
1542        Self::identity_corruption()
1543    }
1544
1545    /// Construct the canonical relation-target entity mismatch corruption error.
1546    pub(crate) fn relation_target_entity_mismatch(
1547        _context_label: &str,
1548        _source_path: &str,
1549        _field_name: &str,
1550        _target_path: &str,
1551        _target_entity_name: &str,
1552        expected_tag: u64,
1553        actual_tag: u64,
1554    ) -> Self {
1555        Self::with_diagnostic_facts(
1556            ErrorClass::Corruption,
1557            ErrorOrigin::Store,
1558            None,
1559            vec![
1560                (
1561                    diagnostic_code::DiagnosticFactTag::ExpectedEntityTag,
1562                    expected_tag,
1563                ),
1564                (
1565                    diagnostic_code::DiagnosticFactTag::ActualEntityTag,
1566                    actual_tag,
1567                ),
1568            ],
1569        )
1570    }
1571
1572    /// Construct the canonical relation-source row decode corruption error.
1573    pub(crate) fn relation_source_row_decode_failed(
1574        _source_path: &str,
1575        _field_name: &str,
1576        _target_path: &str,
1577        _detail: impl Sized,
1578    ) -> Self {
1579        Self::persisted_row_decode_corruption()
1580    }
1581
1582    /// Construct the canonical relation-source unsupported scalar relation-key corruption error.
1583    pub(crate) fn relation_source_row_unsupported_scalar_relation_key(
1584        _source_path: &str,
1585        _field_name: &str,
1586        _target_path: &str,
1587    ) -> Self {
1588        Self::persisted_row_decode_corruption()
1589    }
1590
1591    /// Construct the canonical unsupported relation key-kind corruption error.
1592    pub(crate) fn relation_source_row_unsupported_key_kind(_field_kind: impl fmt::Debug) -> Self {
1593        Self::persisted_row_decode_corruption()
1594    }
1595
1596    /// Construct the canonical covering-component empty-payload corruption error.
1597    pub(crate) fn bytes_covering_component_payload_empty() -> Self {
1598        Self::index_corruption()
1599    }
1600
1601    /// Construct the canonical covering-component truncated bool corruption error.
1602    pub(crate) fn bytes_covering_bool_payload_truncated() -> Self {
1603        Self::index_corruption()
1604    }
1605
1606    /// Construct the canonical covering-component invalid-length corruption error.
1607    pub(crate) fn bytes_covering_component_payload_invalid_length() -> Self {
1608        Self::index_corruption()
1609    }
1610
1611    /// Construct the canonical covering-component invalid-bool corruption error.
1612    pub(crate) fn bytes_covering_bool_payload_invalid_value() -> Self {
1613        Self::index_corruption()
1614    }
1615
1616    /// Construct the canonical covering-component invalid text terminator corruption error.
1617    pub(crate) fn bytes_covering_text_payload_invalid_terminator() -> Self {
1618        Self::index_corruption()
1619    }
1620
1621    /// Construct the canonical covering-component trailing-text corruption error.
1622    pub(crate) fn bytes_covering_text_payload_trailing_bytes() -> Self {
1623        Self::index_corruption()
1624    }
1625
1626    /// Construct the canonical covering-component invalid-UTF-8 text corruption error.
1627    pub(crate) fn bytes_covering_text_payload_invalid_utf8() -> Self {
1628        Self::index_corruption()
1629    }
1630
1631    /// Construct the canonical covering-component invalid text escape corruption error.
1632    pub(crate) fn bytes_covering_text_payload_invalid_escape_byte() -> Self {
1633        Self::index_corruption()
1634    }
1635
1636    /// Construct the canonical covering-component missing text terminator corruption error.
1637    pub(crate) fn bytes_covering_text_payload_missing_terminator() -> Self {
1638        Self::index_corruption()
1639    }
1640
1641    /// Construct an identity-origin corruption error.
1642    pub(crate) fn identity_corruption() -> Self {
1643        Self::new(ErrorClass::Corruption, ErrorOrigin::Identity)
1644    }
1645
1646    /// Construct the canonical identity-control-state corruption error.
1647    pub(crate) fn identity_state_corruption() -> Self {
1648        Self::identity_corruption()
1649    }
1650
1651    /// Construct the typed stale high-water conflict for identity publication.
1652    pub(crate) fn identity_state_conflict() -> Self {
1653        Self::new(ErrorClass::Conflict, ErrorOrigin::Identity)
1654    }
1655
1656    /// Construct the bounded identity-state inventory exhaustion error.
1657    pub(crate) fn identity_state_capacity_exhausted() -> Self {
1658        Self::new(ErrorClass::Unsupported, ErrorOrigin::Identity)
1659    }
1660
1661    /// Construct the exact unsigned identity-domain exhaustion error.
1662    pub(crate) fn identity_exhausted() -> Self {
1663        Self::new(ErrorClass::Unsupported, ErrorOrigin::Identity)
1664    }
1665
1666    /// Construct the bounded pre-key candidate-count exhaustion error.
1667    pub(crate) fn identity_candidate_count_exhausted() -> Self {
1668        Self::new(ErrorClass::Unsupported, ErrorOrigin::Identity)
1669    }
1670
1671    /// Construct a store-origin unsupported error.
1672    #[cold]
1673    #[inline(never)]
1674    pub(crate) fn store_unsupported() -> Self {
1675        Self::new(ErrorClass::Unsupported, ErrorOrigin::Store)
1676    }
1677
1678    /// Construct the typed optimistic/idempotency conflict for schema application.
1679    pub(crate) fn schema_application_conflict() -> Self {
1680        Self::new(ErrorClass::Conflict, ErrorOrigin::Store)
1681    }
1682
1683    /// Construct one typed source-migration lifecycle or planning result.
1684    pub(crate) fn schema_migration(reason: diagnostic_code::SchemaMigrationCode) -> Self {
1685        let class = match reason.diagnostic_code() {
1686            diagnostic_code::DiagnosticCode::RuntimeConflict => ErrorClass::Conflict,
1687            diagnostic_code::DiagnosticCode::RuntimeCorruption => ErrorClass::Corruption,
1688            diagnostic_code::DiagnosticCode::RuntimeUnsupported => ErrorClass::Unsupported,
1689            _ => ErrorClass::Internal,
1690        };
1691        Self {
1692            class,
1693            origin: ErrorOrigin::Store,
1694            detail: Some(ErrorDetail::Store(StoreError::SchemaMigration { reason })),
1695        }
1696    }
1697
1698    /// Construct the canonical schema DDL publication race error.
1699    pub(crate) fn schema_ddl_publication_race_lost(_entity_path: &str) -> Self {
1700        Self {
1701            class: ErrorClass::Unsupported,
1702            origin: ErrorOrigin::Store,
1703            detail: Some(ErrorDetail::Store(StoreError::SchemaDdlPublicationRaceLost)),
1704        }
1705    }
1706
1707    /// Construct the canonical current physical-rewrite migration rejection.
1708    #[cfg(feature = "sql")]
1709    pub(crate) fn schema_ddl_rewrite_requires_migration(_entity_path: &str) -> Self {
1710        Self {
1711            class: ErrorClass::Unsupported,
1712            origin: ErrorOrigin::Store,
1713            detail: Some(ErrorDetail::Store(
1714                StoreError::SchemaDdlRewriteRequiresMigration,
1715            )),
1716        }
1717    }
1718
1719    /// Construct the fail-closed journal mutation-revision exhaustion error.
1720    pub(crate) fn journal_mutation_revision_exhausted() -> Self {
1721        Self {
1722            class: ErrorClass::Unsupported,
1723            origin: ErrorOrigin::Store,
1724            detail: Some(ErrorDetail::Store(
1725                StoreError::JournalMutationRevisionExhausted,
1726            )),
1727        }
1728    }
1729
1730    /// Construct a bounded schema-transition resource rejection.
1731    pub(crate) fn schema_transition_budget_exceeded(
1732        resource: SchemaTransitionBudgetResource,
1733    ) -> Self {
1734        Self {
1735            class: ErrorClass::Unsupported,
1736            origin: ErrorOrigin::Store,
1737            detail: Some(ErrorDetail::Store(
1738                StoreError::SchemaTransitionBudgetExceeded { resource },
1739            )),
1740        }
1741    }
1742
1743    /// Construct the canonical unsupported persisted entity-tag store error.
1744    pub(crate) fn unsupported_entity_tag_in_data_store(
1745        _entity_tag: crate::types::EntityTag,
1746    ) -> Self {
1747        Self::store_unsupported()
1748    }
1749
1750    /// Construct the canonical commit-memory id registration failure.
1751    #[cfg(not(test))]
1752    pub(crate) fn commit_memory_id_registration_failed(_err: impl Sized) -> Self {
1753        Self::store_internal()
1754    }
1755
1756    /// Construct an index-origin unsupported error.
1757    pub(crate) fn index_unsupported() -> Self {
1758        Self::new(ErrorClass::Unsupported, ErrorOrigin::Index)
1759    }
1760
1761    /// Construct the canonical index-key component size-limit unsupported error.
1762    pub(crate) fn index_component_exceeds_max_size_at(
1763        entity_tag: u64,
1764        physical_generation: u64,
1765        component_index: usize,
1766        actual_length: usize,
1767        limit: usize,
1768    ) -> Self {
1769        Self::with_diagnostic_facts(
1770            ErrorClass::Unsupported,
1771            ErrorOrigin::Index,
1772            None,
1773            vec![
1774                (diagnostic_code::DiagnosticFactTag::EntityTag, entity_tag),
1775                (
1776                    diagnostic_code::DiagnosticFactTag::PhysicalGeneration,
1777                    physical_generation,
1778                ),
1779                (
1780                    diagnostic_code::DiagnosticFactTag::ComponentIndex,
1781                    component_index as u64,
1782                ),
1783                (
1784                    diagnostic_code::DiagnosticFactTag::ComponentKind,
1785                    diagnostic_code::DiagnosticComponentKind::IndexKeyComponent.raw(),
1786                ),
1787                (
1788                    diagnostic_code::DiagnosticFactTag::ActualLength,
1789                    actual_length as u64,
1790                ),
1791                (diagnostic_code::DiagnosticFactTag::Limit, limit as u64),
1792            ],
1793        )
1794    }
1795
1796    /// Construct the canonical index-key component size-limit error when the
1797    /// generic caller has not retained one accepted index identity.
1798    pub(crate) fn index_component_exceeds_max_size() -> Self {
1799        Self::index_unsupported()
1800    }
1801
1802    /// Construct a serialize-origin unsupported error.
1803    pub(crate) fn serialize_unsupported() -> Self {
1804        Self::new(ErrorClass::Unsupported, ErrorOrigin::Serialize)
1805    }
1806
1807    /// Construct a cursor-origin invalid-continuation error.
1808    pub(crate) fn cursor_invalid_continuation() -> Self {
1809        Self::new(ErrorClass::Unsupported, ErrorOrigin::Cursor)
1810    }
1811
1812    /// Construct a serialize-origin incompatible persisted-format error.
1813    pub(crate) fn serialize_incompatible_persisted_format() -> Self {
1814        Self::new(
1815            ErrorClass::IncompatiblePersistedFormat,
1816            ErrorOrigin::Serialize,
1817        )
1818    }
1819
1820    /// Construct a query-origin unsupported error preserving one SQL parser
1821    /// unsupported-feature code in structured error detail.
1822    #[cfg(feature = "sql")]
1823    pub(crate) fn query_unsupported_sql_feature(feature: diagnostic_code::SqlFeatureCode) -> Self {
1824        Self {
1825            class: ErrorClass::Unsupported,
1826            origin: ErrorOrigin::Query,
1827            detail: Some(ErrorDetail::Query(
1828                QueryErrorDetail::UnsupportedSqlFeature { feature },
1829            )),
1830        }
1831    }
1832
1833    /// Construct a query-origin unsupported SQL lowering error preserving one
1834    /// compact lowering reason in structured error detail.
1835    #[cfg(feature = "sql")]
1836    pub(crate) fn query_sql_lowering(reason: diagnostic_code::SqlLoweringCode) -> Self {
1837        Self {
1838            class: ErrorClass::Unsupported,
1839            origin: ErrorOrigin::Query,
1840            detail: Some(ErrorDetail::Query(QueryErrorDetail::SqlLowering { reason })),
1841        }
1842    }
1843
1844    /// Construct one query-origin SQL lowering error with bounded numeric context.
1845    #[cfg(feature = "sql")]
1846    pub(crate) fn query_sql_lowering_with_facts(
1847        reason: diagnostic_code::SqlLoweringCode,
1848        facts: Vec<(diagnostic_code::DiagnosticFactTag, u64)>,
1849    ) -> Self {
1850        Self::with_diagnostic_facts(
1851            ErrorClass::Unsupported,
1852            ErrorOrigin::Query,
1853            Some(diagnostic_code::DiagnosticDetail::SqlLowering { reason }),
1854            facts,
1855        )
1856    }
1857
1858    /// Construct a query-origin unsupported projection error preserving one
1859    /// compact projection reason in structured error detail.
1860    pub(crate) fn query_unsupported_projection(
1861        reason: diagnostic_code::QueryProjectionCode,
1862    ) -> Self {
1863        Self {
1864            class: ErrorClass::Unsupported,
1865            origin: ErrorOrigin::Query,
1866            detail: Some(ErrorDetail::Query(
1867                QueryErrorDetail::UnsupportedProjection { reason },
1868            )),
1869        }
1870    }
1871
1872    /// Construct a query-origin unsupported aggregate target-field error.
1873    pub(crate) fn query_unknown_aggregate_target_field() -> Self {
1874        Self {
1875            class: ErrorClass::Unsupported,
1876            origin: ErrorOrigin::Query,
1877            detail: Some(ErrorDetail::Query(
1878                QueryErrorDetail::UnknownAggregateTargetField,
1879            )),
1880        }
1881    }
1882
1883    /// Construct a query-origin unsupported error preserving one SQL endpoint
1884    /// surface mismatch in structured error detail.
1885    #[cfg(feature = "sql")]
1886    pub(crate) fn query_sql_surface_mismatch(
1887        mismatch: diagnostic_code::SqlSurfaceMismatchCode,
1888    ) -> Self {
1889        Self {
1890            class: ErrorClass::Unsupported,
1891            origin: ErrorOrigin::Query,
1892            detail: Some(ErrorDetail::Query(QueryErrorDetail::SqlSurfaceMismatch {
1893                mismatch,
1894            })),
1895        }
1896    }
1897
1898    /// Construct a query-origin unsupported SQL write boundary error.
1899    pub(crate) fn query_sql_write_boundary(
1900        boundary: diagnostic_code::SqlWriteBoundaryCode,
1901    ) -> Self {
1902        Self {
1903            class: ErrorClass::Unsupported,
1904            origin: ErrorOrigin::Query,
1905            detail: Some(ErrorDetail::Query(QueryErrorDetail::SqlWriteBoundary {
1906                boundary,
1907            })),
1908        }
1909    }
1910
1911    /// Construct one query-origin SQL write-boundary error with bounded numeric context.
1912    pub(crate) fn query_sql_write_boundary_with_facts(
1913        boundary: diagnostic_code::SqlWriteBoundaryCode,
1914        facts: Vec<(diagnostic_code::DiagnosticFactTag, u64)>,
1915    ) -> Self {
1916        Self::with_diagnostic_facts(
1917            ErrorClass::Unsupported,
1918            ErrorOrigin::Query,
1919            Some(diagnostic_code::DiagnosticDetail::SqlWriteBoundary { boundary }),
1920            facts,
1921        )
1922    }
1923
1924    pub fn store_not_found(_key: impl Sized) -> Self {
1925        Self {
1926            class: ErrorClass::NotFound,
1927            origin: ErrorOrigin::Store,
1928            detail: Some(ErrorDetail::Store(StoreError::NotFound)),
1929        }
1930    }
1931
1932    /// Construct a standardized unsupported-entity-path error.
1933    pub fn unsupported_entity_path(_path: impl Sized) -> Self {
1934        Self::store_unsupported()
1935    }
1936
1937    /// Construct an index-plan corruption error with a canonical prefix.
1938    #[cold]
1939    #[inline(never)]
1940    pub(crate) fn index_plan_corruption(origin: ErrorOrigin) -> Self {
1941        Self::new(ErrorClass::Corruption, origin)
1942    }
1943
1944    /// Construct an index-plan corruption error for index-origin failures.
1945    #[cold]
1946    #[inline(never)]
1947    pub(crate) fn index_plan_index_corruption() -> Self {
1948        Self::index_plan_corruption(ErrorOrigin::Index)
1949    }
1950
1951    /// Construct an index-plan corruption error for store-origin failures.
1952    #[cold]
1953    #[inline(never)]
1954    pub(crate) fn index_plan_store_corruption() -> Self {
1955        Self::index_plan_corruption(ErrorOrigin::Store)
1956    }
1957
1958    /// Construct an index-plan corruption error for serialize-origin failures.
1959    #[cold]
1960    #[inline(never)]
1961    pub(crate) fn index_plan_serialize_corruption() -> Self {
1962        Self::index_plan_corruption(ErrorOrigin::Serialize)
1963    }
1964
1965    /// Construct an index-plan invariant violation error with a canonical prefix.
1966    #[cfg(test)]
1967    pub(crate) fn index_plan_invariant(origin: ErrorOrigin) -> Self {
1968        Self::new(ErrorClass::InvariantViolation, origin)
1969    }
1970
1971    /// Construct an index-plan invariant violation error for store-origin failures.
1972    #[cfg(test)]
1973    pub(crate) fn index_plan_store_invariant() -> Self {
1974        Self::index_plan_invariant(ErrorOrigin::Store)
1975    }
1976
1977    /// Construct an index-origin conflict without claiming accepted identity.
1978    ///
1979    /// Live accepted uniqueness violations use compact accepted-constraint facts.
1980    /// Schema-domain staging and activation findings use this compact
1981    /// classification before an accepted write-admission diagnostic exists.
1982    pub(crate) fn index_conflict() -> Self {
1983        Self::new(ErrorClass::Conflict, ErrorOrigin::Index)
1984    }
1985}
1986
1987impl From<diagnostic_code::QueryReadAdmissionCode> for InternalError {
1988    fn from(reason: diagnostic_code::QueryReadAdmissionCode) -> Self {
1989        Self {
1990            class: ErrorClass::Unsupported,
1991            origin: ErrorOrigin::Query,
1992            detail: Some(ErrorDetail::Query(QueryErrorDetail::QueryReadAdmission {
1993                reason,
1994            })),
1995        }
1996    }
1997}
1998
1999impl fmt::Debug for InternalError {
2000    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2001        fmt_compact_diagnostic(
2002            f,
2003            self.diagnostic_code(),
2004            self.detail
2005                .as_ref()
2006                .and_then(ErrorDetail::diagnostic_detail),
2007        )
2008    }
2009}
2010
2011impl fmt::Display for InternalError {
2012    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2013        f.write_str(self.message())
2014    }
2015}
2016
2017impl std::error::Error for InternalError {}
2018
2019///
2020/// ConstraintValuePathComponent
2021///
2022/// Stable accepted identity or finite-value coordinate in one targeted-rule
2023/// violation. Display names are deliberately absent so renames cannot change
2024/// the diagnostic identity.
2025///
2026
2027#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq)]
2028pub enum ConstraintValuePathComponent {
2029    /// Persisted root field whose admitted value was traversed.
2030    RootField { field_id: u32 },
2031
2032    /// Accepted record member selected by immutable composite/member identity.
2033    RecordMember {
2034        composite_type_id: u32,
2035        member_id: u32,
2036    },
2037
2038    /// Tuple element selected by accepted composite identity and ordinal.
2039    TupleElement {
2040        composite_type_id: u32,
2041        ordinal: u32,
2042    },
2043
2044    /// Transparent accepted newtype boundary.
2045    Newtype { composite_type_id: u32 },
2046
2047    /// Selected accepted enum variant.
2048    EnumVariant { enum_type_id: u32, variant_id: u32 },
2049
2050    /// List element in admitted order.
2051    ListElement { index: u32 },
2052
2053    /// Set element in canonical admitted order.
2054    SetElement { index: u32 },
2055
2056    /// Map key in canonical entry order.
2057    MapEntryKey { index: u32 },
2058
2059    /// Map value in canonical entry order.
2060    MapEntryValue { index: u32 },
2061}
2062
2063impl fmt::Display for ConstraintValuePathComponent {
2064    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2065        match self {
2066            Self::RootField { field_id } => write!(f, "field#{field_id}"),
2067            Self::RecordMember {
2068                composite_type_id,
2069                member_id,
2070            } => write!(f, "record#{composite_type_id}.member#{member_id}"),
2071            Self::TupleElement {
2072                composite_type_id,
2073                ordinal,
2074            } => write!(f, "tuple#{composite_type_id}[{ordinal}]"),
2075            Self::Newtype { composite_type_id } => write!(f, "newtype#{composite_type_id}"),
2076            Self::EnumVariant {
2077                enum_type_id,
2078                variant_id,
2079            } => write!(f, "enum#{enum_type_id}.variant#{variant_id}"),
2080            Self::ListElement { index } => write!(f, "list[{index}]"),
2081            Self::SetElement { index } => write!(f, "set[{index}]"),
2082            Self::MapEntryKey { index } => write!(f, "map[{index}].key"),
2083            Self::MapEntryValue { index } => write!(f, "map[{index}].value"),
2084        }
2085    }
2086}
2087
2088///
2089/// ConstraintValuePath
2090///
2091/// Bounded typed path to the first deterministic failing value occurrence.
2092///
2093
2094#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
2095pub struct ConstraintValuePath {
2096    components: Vec<ConstraintValuePathComponent>,
2097}
2098
2099impl ConstraintValuePath {
2100    /// Build one already-bounded accepted occurrence path.
2101    #[must_use]
2102    pub(crate) const fn new(components: Vec<ConstraintValuePathComponent>) -> Self {
2103        Self { components }
2104    }
2105
2106    /// Borrow the stable accepted components.
2107    #[must_use]
2108    pub const fn components(&self) -> &[ConstraintValuePathComponent] {
2109        self.components.as_slice()
2110    }
2111}
2112
2113impl fmt::Display for ConstraintValuePath {
2114    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2115        for (ordinal, component) in self.components.iter().enumerate() {
2116            if ordinal != 0 {
2117                f.write_str("/")?;
2118            }
2119            component.fmt(f)?;
2120        }
2121        Ok(())
2122    }
2123}
2124
2125///
2126/// ConstraintValidationFindingOutput
2127///
2128/// Bounded historical validation evidence returned only by explicit schema
2129/// validation operations. Names are resolved by host tooling from the exact
2130/// accepted fingerprint and immutable numeric identities.
2131///
2132
2133#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
2134pub struct ConstraintValidationFindingOutput {
2135    accepted_schema_fingerprint: [u8; 16],
2136    entity_tag: u64,
2137    constraint_id: u32,
2138    primary_key: Vec<u8>,
2139    field_ids: Vec<u32>,
2140    value_path: Option<ConstraintValuePath>,
2141    error_code: u16,
2142}
2143
2144impl ConstraintValidationFindingOutput {
2145    /// Build one already-bounded historical validation finding.
2146    #[must_use]
2147    pub(crate) const fn new(
2148        accepted_schema_fingerprint: [u8; 16],
2149        entity_tag: u64,
2150        constraint_id: u32,
2151        primary_key: Vec<u8>,
2152        field_ids: Vec<u32>,
2153        value_path: Option<ConstraintValuePath>,
2154        error_code: u16,
2155    ) -> Self {
2156        Self {
2157            accepted_schema_fingerprint,
2158            entity_tag,
2159            constraint_id,
2160            primary_key,
2161            field_ids,
2162            value_path,
2163            error_code,
2164        }
2165    }
2166
2167    /// Return the exact accepted-schema fingerprint that binds every numeric identity.
2168    #[must_use]
2169    pub const fn accepted_schema_fingerprint(&self) -> [u8; 16] {
2170        self.accepted_schema_fingerprint
2171    }
2172
2173    /// Return the stable accepted entity identity.
2174    #[must_use]
2175    pub const fn entity_tag(&self) -> u64 {
2176        self.entity_tag
2177    }
2178
2179    /// Return the stable accepted constraint identity.
2180    #[must_use]
2181    pub const fn constraint_id(&self) -> u32 {
2182        self.constraint_id
2183    }
2184
2185    /// Borrow the bounded canonical persisted primary-key locator.
2186    #[must_use]
2187    pub const fn primary_key(&self) -> &[u8] {
2188        self.primary_key.as_slice()
2189    }
2190
2191    /// Borrow immutable accepted field identities implicated by the finding.
2192    #[must_use]
2193    pub const fn field_ids(&self) -> &[u32] {
2194        self.field_ids.as_slice()
2195    }
2196
2197    /// Borrow the typed concrete value path for a targeted-rule violation.
2198    #[must_use]
2199    pub const fn value_path(&self) -> Option<&ConstraintValuePath> {
2200        self.value_path.as_ref()
2201    }
2202
2203    /// Return the compact stable error code for this exact failure.
2204    #[must_use]
2205    pub const fn error_code(&self) -> diagnostic_code::ErrorCode {
2206        diagnostic_code::ErrorCode::from_raw(self.error_code)
2207    }
2208
2209    /// Return the broad public error class derived from the compact code.
2210    #[must_use]
2211    pub const fn error_class(&self) -> diagnostic_code::ErrorClass {
2212        self.error_code().class()
2213    }
2214}
2215
2216/// Complete bounded numeric authority needed to publish E223 or E225 facts.
2217#[derive(Clone)]
2218pub(crate) struct AcceptedConstraintFactContext {
2219    fingerprint_method: u8,
2220    accepted_schema_fingerprint: [u8; 16],
2221    entity_tag: u64,
2222    constraint_id: u32,
2223    constraint_kind: diagnostic_code::DiagnosticConstraintKind,
2224    mutation: Option<MutationDiagnosticContext>,
2225    value_path: Option<ConstraintValuePath>,
2226}
2227
2228impl AcceptedConstraintFactContext {
2229    #[must_use]
2230    pub(crate) fn write_admission(
2231        fingerprint_method: u8,
2232        accepted_schema_fingerprint: [u8; 16],
2233        entity_tag: u64,
2234        constraint_id: u32,
2235        constraint_kind: diagnostic_code::DiagnosticConstraintKind,
2236        mutation: Option<MutationDiagnosticContext>,
2237        value_path: Option<ConstraintValuePath>,
2238    ) -> Self {
2239        debug_assert!(mutation.is_none_or(|context| context.entity_tag() == entity_tag));
2240        Self {
2241            fingerprint_method,
2242            accepted_schema_fingerprint,
2243            entity_tag,
2244            constraint_id,
2245            constraint_kind,
2246            mutation,
2247            value_path,
2248        }
2249    }
2250
2251    fn facts(self) -> Vec<(diagnostic_code::DiagnosticFactTag, u64)> {
2252        let high = u64::from_be_bytes([
2253            self.accepted_schema_fingerprint[0],
2254            self.accepted_schema_fingerprint[1],
2255            self.accepted_schema_fingerprint[2],
2256            self.accepted_schema_fingerprint[3],
2257            self.accepted_schema_fingerprint[4],
2258            self.accepted_schema_fingerprint[5],
2259            self.accepted_schema_fingerprint[6],
2260            self.accepted_schema_fingerprint[7],
2261        ]);
2262        let low = u64::from_be_bytes([
2263            self.accepted_schema_fingerprint[8],
2264            self.accepted_schema_fingerprint[9],
2265            self.accepted_schema_fingerprint[10],
2266            self.accepted_schema_fingerprint[11],
2267            self.accepted_schema_fingerprint[12],
2268            self.accepted_schema_fingerprint[13],
2269            self.accepted_schema_fingerprint[14],
2270            self.accepted_schema_fingerprint[15],
2271        ]);
2272        let path_len = self
2273            .value_path
2274            .as_ref()
2275            .map_or(0, |path| path.components().len());
2276        let mutation_fact_count = self.mutation.map_or(0, |mutation| {
2277            1 + usize::from(mutation.batch_position.is_some())
2278        });
2279        let mut facts = Vec::with_capacity(7 + mutation_fact_count + path_len);
2280        facts.push((
2281            diagnostic_code::DiagnosticFactTag::AcceptedSchemaFingerprintMethod,
2282            u64::from(self.fingerprint_method),
2283        ));
2284        facts.push((
2285            diagnostic_code::DiagnosticFactTag::AcceptedSchemaFingerprintHigh,
2286            high,
2287        ));
2288        facts.push((
2289            diagnostic_code::DiagnosticFactTag::AcceptedSchemaFingerprintLow,
2290            low,
2291        ));
2292        facts.push((
2293            diagnostic_code::DiagnosticFactTag::EntityTag,
2294            self.entity_tag,
2295        ));
2296        facts.push((
2297            diagnostic_code::DiagnosticFactTag::ConstraintId,
2298            u64::from(self.constraint_id),
2299        ));
2300        facts.push((
2301            diagnostic_code::DiagnosticFactTag::ConstraintKind,
2302            self.constraint_kind.raw(),
2303        ));
2304        facts.push((
2305            diagnostic_code::DiagnosticFactTag::ConstraintContext,
2306            diagnostic_code::DiagnosticConstraintContext::WriteAdmission.raw(),
2307        ));
2308        if let Some(mutation) = self.mutation {
2309            mutation.append_operation_facts(&mut facts);
2310        }
2311        if let Some(path) = self.value_path {
2312            for component in path.components {
2313                facts.push(constraint_value_path_fact(component));
2314            }
2315        }
2316        debug_assert!(facts.len() <= diagnostic_code::MAX_PUBLIC_DIAGNOSTIC_FACTS);
2317        facts
2318    }
2319}
2320
2321fn constraint_value_path_fact(
2322    component: ConstraintValuePathComponent,
2323) -> (diagnostic_code::DiagnosticFactTag, u64) {
2324    use diagnostic_code::DiagnosticFactTag;
2325    match component {
2326        ConstraintValuePathComponent::RootField { field_id } => {
2327            (DiagnosticFactTag::RootField, u64::from(field_id))
2328        }
2329        ConstraintValuePathComponent::RecordMember {
2330            composite_type_id,
2331            member_id,
2332        } => (
2333            DiagnosticFactTag::RecordMember,
2334            diagnostic_code::pack_u32_pair(composite_type_id, member_id),
2335        ),
2336        ConstraintValuePathComponent::TupleElement {
2337            composite_type_id,
2338            ordinal,
2339        } => (
2340            DiagnosticFactTag::TupleElement,
2341            diagnostic_code::pack_u32_pair(composite_type_id, ordinal),
2342        ),
2343        ConstraintValuePathComponent::Newtype { composite_type_id } => {
2344            (DiagnosticFactTag::Newtype, u64::from(composite_type_id))
2345        }
2346        ConstraintValuePathComponent::EnumVariant {
2347            enum_type_id,
2348            variant_id,
2349        } => (
2350            DiagnosticFactTag::EnumVariant,
2351            diagnostic_code::pack_u32_pair(enum_type_id, variant_id),
2352        ),
2353        ConstraintValuePathComponent::ListElement { index } => {
2354            (DiagnosticFactTag::ListElement, u64::from(index))
2355        }
2356        ConstraintValuePathComponent::SetElement { index } => {
2357            (DiagnosticFactTag::SetElement, u64::from(index))
2358        }
2359        ConstraintValuePathComponent::MapEntryKey { index } => {
2360            (DiagnosticFactTag::MapEntryKey, u64::from(index))
2361        }
2362        ConstraintValuePathComponent::MapEntryValue { index } => {
2363            (DiagnosticFactTag::MapEntryValue, u64::from(index))
2364        }
2365    }
2366}
2367
2368///
2369/// ErrorDetail
2370///
2371/// Structured, origin-specific error detail carried by [`InternalError`].
2372/// This enum is intentionally extensible.
2373///
2374
2375pub enum ErrorDetail {
2376    /// Compact code/detail plus safe numeric context for one public failure.
2377    DiagnosticFacts(Box<DiagnosticFactDetail>),
2378    /// Executor-owned mutation and query execution details.
2379    Executor(ExecutorErrorDetail),
2380    Store(StoreError),
2381    Query(QueryErrorDetail),
2382    Recovery(RecoveryErrorDetail),
2383    // Future-proofing:
2384    // Index(IndexError),
2385}
2386
2387/// Executor-specific structured error detail.
2388pub enum ExecutorErrorDetail {
2389    /// A complete insert or replacement omitted one or more required fields.
2390    MutationRequiredFieldMissing,
2391    /// A logical mutation would move accepted managed time backward.
2392    MutationManagedTimestampRegression,
2393    /// A caller explicitly authored a field owned by accepted database policy.
2394    MutationDatabaseOwnedFieldExplicit,
2395    /// A mixed structural mutation batch contained no operations.
2396    MutationBatchEmpty,
2397    /// A mixed structural mutation batch exceeded its operation-count bound.
2398    MutationBatchTooManyItems,
2399    /// A mixed structural mutation batch exceeded its staged-byte bound.
2400    MutationBatchStagedBytesExceeded,
2401    /// A mixed structural mutation result exceeded its encoded response bound.
2402    MutationBatchResultBytesExceeded,
2403    /// A mixed structural mutation batch resolved to more than one accepted entity.
2404    MutationBatchEntityMismatch,
2405    /// More than one mixed structural operation targeted the same accepted key.
2406    MutationBatchDuplicateKey,
2407    /// Accepted row-constraint metadata or compiled state was inconsistent.
2408    AcceptedRowConstraintProgramCorrupt,
2409}
2410
2411///
2412/// RecoveryErrorDetail
2413///
2414/// Recovery-origin structured error detail payload.
2415///
2416
2417pub enum RecoveryErrorDetail {
2418    UnsupportedFormatVersion { found: Option<u16>, required: u16 },
2419
2420    MalformedFormatMarker { reason: RecoveryFormatMarkerError },
2421}
2422
2423/// Store boot-marker corruption classification.
2424#[derive(Clone, Copy, Eq, PartialEq)]
2425pub enum RecoveryFormatMarkerError {
2426    Magic,
2427    Checksum,
2428    State,
2429}
2430
2431impl RecoveryFormatMarkerError {
2432    const fn diagnostic_decode_reason(self) -> diagnostic_code::DiagnosticDecodeReason {
2433        match self {
2434            Self::Magic => diagnostic_code::DiagnosticDecodeReason::RecoveryMarkerMagic,
2435            Self::Checksum => diagnostic_code::DiagnosticDecodeReason::RecoveryMarkerChecksum,
2436            Self::State => diagnostic_code::DiagnosticDecodeReason::RecoveryMarkerState,
2437        }
2438    }
2439}
2440
2441///
2442/// StoreError
2443///
2444/// Store-specific structured error detail.
2445/// Never returned directly; always wrapped in [`ErrorDetail::Store`].
2446///
2447
2448pub enum StoreError {
2449    NotFound,
2450
2451    Corrupt,
2452
2453    InvariantViolation,
2454
2455    SchemaDdlPublicationRaceLost,
2456
2457    SchemaDdlRewriteRequiresMigration,
2458
2459    SchemaMigration {
2460        reason: diagnostic_code::SchemaMigrationCode,
2461    },
2462
2463    SchemaRowLayoutVersionExhausted,
2464
2465    JournalMutationRevisionExhausted,
2466
2467    SchemaTransitionBudgetExceeded {
2468        resource: SchemaTransitionBudgetResource,
2469    },
2470
2471    /// A generated field would collide with an accepted DDL-owned slot.
2472    SchemaGeneratedFieldAfterDdlField,
2473
2474    /// A live generated constraint activation no longer matches its proposal.
2475    SchemaGeneratedConstraintActivationStale,
2476}
2477
2478///
2479/// QueryErrorDetail
2480///
2481/// Query-origin structured error detail payload.
2482///
2483
2484pub enum QueryErrorDetail {
2485    NumericOverflow,
2486
2487    NumericNotRepresentable,
2488
2489    UnsupportedSqlFeature {
2490        feature: diagnostic_code::SqlFeatureCode,
2491    },
2492
2493    SqlLowering {
2494        reason: diagnostic_code::SqlLoweringCode,
2495    },
2496
2497    UnsupportedProjection {
2498        reason: diagnostic_code::QueryProjectionCode,
2499    },
2500
2501    UnknownAggregateTargetField,
2502
2503    ResultShapeMismatch {
2504        reason: diagnostic_code::QueryResultShapeCode,
2505    },
2506
2507    QueryReadAdmission {
2508        reason: diagnostic_code::QueryReadAdmissionCode,
2509    },
2510
2511    SqlSurfaceMismatch {
2512        mismatch: diagnostic_code::SqlSurfaceMismatchCode,
2513    },
2514
2515    SqlWriteBoundary {
2516        boundary: diagnostic_code::SqlWriteBoundaryCode,
2517    },
2518
2519    SchemaDdlAdmission {
2520        error: SchemaDdlAdmissionError,
2521    },
2522
2523    StaleSchemaRevision,
2524}
2525
2526impl fmt::Display for QueryErrorDetail {
2527    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2528        f.write_str(COMPACT_QUERY_DIAGNOSTIC_MESSAGE)
2529    }
2530}
2531
2532impl std::error::Error for QueryErrorDetail {}
2533
2534///
2535/// SchemaTransitionBudgetResource
2536///
2537/// Query-visible identity of the exact schema-transition resource cap that
2538/// rejected a complete validation or derived-state stage.
2539///
2540
2541#[derive(Clone, Copy, Debug, Eq, PartialEq)]
2542pub enum SchemaTransitionBudgetResource {
2543    /// Number of physical deletion keys retained for replacement.
2544    DeletionKeys,
2545    /// Number of row-derived projection entries retained for validation.
2546    ProjectionEntries,
2547    /// Deterministic projection and physical-classification work units.
2548    ProjectionWorkUnits,
2549    /// Number of authoritative source rows.
2550    SourceRows,
2551    /// Cumulative bytes of authoritative source rows.
2552    SourceRowBytes,
2553    /// Retained raw payloads plus deterministic-sort workspace bytes.
2554    StagedRawBytes,
2555}
2556
2557///
2558/// SchemaDdlAdmissionError
2559///
2560/// Stable query-visible SQL DDL admission reason. Human diagnostics may carry
2561/// extra version, fingerprint, and target facts beside this machine-readable
2562/// variant.
2563///
2564
2565#[derive(Clone, Copy, Eq, PartialEq)]
2566pub enum SchemaDdlAdmissionError {
2567    MissingExpectedSchemaVersion,
2568
2569    MissingNextSchemaVersion,
2570
2571    StaleExpectedSchemaVersion,
2572
2573    InvalidExpectedSchemaVersion,
2574
2575    InvalidNextSchemaVersion,
2576
2577    AcceptedSchemaChangeWithoutVersionBump,
2578
2579    EmptyVersionBump,
2580
2581    VersionGap,
2582
2583    VersionRollback,
2584
2585    FingerprintMethodMismatch,
2586
2587    UnsupportedTransitionClass,
2588
2589    PhysicalRunnerMissing,
2590
2591    ValidationFailed,
2592
2593    PublicationRaceLost,
2594
2595    InvalidAddColumnDefault,
2596
2597    InvalidAlterColumnDefault,
2598
2599    RowLayoutVersionExhausted,
2600
2601    GeneratedIndexDropRejected,
2602
2603    SchemaRewriteRequiresMigration,
2604
2605    SchemaTransitionBudgetExceeded {
2606        resource: SchemaTransitionBudgetResource,
2607    },
2608
2609    GeneratedFieldDefaultChangeRejected,
2610
2611    GeneratedFieldNullabilityChangeRejected,
2612}
2613
2614impl fmt::Display for SchemaDdlAdmissionError {
2615    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2616        f.write_str(COMPACT_QUERY_DIAGNOSTIC_MESSAGE)
2617    }
2618}
2619
2620impl std::error::Error for SchemaDdlAdmissionError {}
2621
2622impl fmt::Debug for ErrorDetail {
2623    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2624        fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2625    }
2626}
2627
2628impl fmt::Debug for ExecutorErrorDetail {
2629    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2630        fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2631    }
2632}
2633
2634impl fmt::Debug for StoreError {
2635    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2636        fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2637    }
2638}
2639
2640impl fmt::Debug for QueryErrorDetail {
2641    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2642        fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2643    }
2644}
2645
2646impl fmt::Debug for RecoveryErrorDetail {
2647    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2648        fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
2649    }
2650}
2651
2652impl fmt::Debug for RecoveryFormatMarkerError {
2653    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2654        fmt_compact_diagnostic(
2655            f,
2656            diagnostic_code::DiagnosticCode::RuntimeCorruption,
2657            Some(diagnostic_code::DiagnosticDetail::RuntimeKind {
2658                kind: diagnostic_code::RuntimeErrorKind::Corruption,
2659            }),
2660        )
2661    }
2662}
2663
2664impl fmt::Debug for SchemaDdlAdmissionError {
2665    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2666        fmt_compact_diagnostic(
2667            f,
2668            diagnostic_code::DiagnosticCode::SchemaDdlAdmission,
2669            Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2670                reason: self.diagnostic_code(),
2671            }),
2672        )
2673    }
2674}
2675
2676fn fmt_compact_diagnostic(
2677    f: &mut fmt::Formatter<'_>,
2678    code: diagnostic_code::DiagnosticCode,
2679    detail: Option<diagnostic_code::DiagnosticDetail>,
2680) -> fmt::Result {
2681    write!(
2682        f,
2683        "{}",
2684        diagnostic_code::ErrorCode::from_parts(code, detail).raw()
2685    )
2686}
2687
2688impl ErrorDetail {
2689    /// Return the compact diagnostic code for this structured detail.
2690    #[must_use]
2691    pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2692        match self {
2693            Self::DiagnosticFacts(detail) => detail.diagnostic.code(),
2694            Self::Executor(error) => error.diagnostic_code(),
2695            Self::Store(error) => error.diagnostic_code(),
2696            Self::Query(error) => error.diagnostic_code(),
2697            Self::Recovery(error) => error.diagnostic_code(),
2698        }
2699    }
2700
2701    /// Return compact structured diagnostic detail when the payload carries one.
2702    #[must_use]
2703    pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2704        match self {
2705            Self::DiagnosticFacts(detail) => detail.diagnostic.detail().copied(),
2706            Self::Executor(error) => error.diagnostic_detail(),
2707            Self::Store(error) => error.diagnostic_detail(),
2708            Self::Query(error) => error.diagnostic_detail(),
2709            Self::Recovery(error) => error.diagnostic_detail(),
2710        }
2711    }
2712
2713    /// Project safe typed detail into canonical public numeric facts.
2714    #[must_use]
2715    #[cold]
2716    #[inline(never)]
2717    pub fn diagnostic_facts(&self) -> Vec<(diagnostic_code::DiagnosticFactTag, u64)> {
2718        match self {
2719            Self::DiagnosticFacts(detail) => detail.facts.clone(),
2720            Self::Executor(error) => error.diagnostic_facts(),
2721            Self::Query(error) => error.diagnostic_facts(),
2722            Self::Recovery(error) => error.diagnostic_facts(),
2723            Self::Store(_) => Vec::new(),
2724        }
2725    }
2726}
2727
2728impl ExecutorErrorDetail {
2729    /// Return the compact diagnostic code for this executor detail.
2730    #[must_use]
2731    pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2732        match self {
2733            Self::MutationRequiredFieldMissing
2734            | Self::MutationDatabaseOwnedFieldExplicit
2735            | Self::MutationBatchEmpty
2736            | Self::MutationBatchTooManyItems
2737            | Self::MutationBatchStagedBytesExceeded
2738            | Self::MutationBatchResultBytesExceeded => {
2739                diagnostic_code::DiagnosticCode::RuntimeUnsupported
2740            }
2741            Self::MutationBatchEntityMismatch | Self::MutationBatchDuplicateKey => {
2742                diagnostic_code::DiagnosticCode::RuntimeConflict
2743            }
2744            Self::MutationManagedTimestampRegression => {
2745                diagnostic_code::DiagnosticCode::RuntimeInvariantViolation
2746            }
2747            Self::AcceptedRowConstraintProgramCorrupt => {
2748                diagnostic_code::DiagnosticCode::RuntimeCorruption
2749            }
2750        }
2751    }
2752
2753    /// Return compact structured diagnostic detail for this executor detail.
2754    #[must_use]
2755    pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2756        match self {
2757            Self::MutationRequiredFieldMissing => {
2758                Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2759                    boundary: diagnostic_code::RuntimeBoundaryCode::MutationRequiredFieldMissing,
2760                })
2761            }
2762            Self::MutationDatabaseOwnedFieldExplicit => {
2763                Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2764                    boundary:
2765                        diagnostic_code::RuntimeBoundaryCode::MutationDatabaseOwnedFieldExplicit,
2766                })
2767            }
2768            Self::MutationBatchEmpty => Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2769                boundary: diagnostic_code::RuntimeBoundaryCode::MutationBatchEmpty,
2770            }),
2771            Self::MutationBatchTooManyItems => {
2772                Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2773                    boundary: diagnostic_code::RuntimeBoundaryCode::MutationBatchTooManyItems,
2774                })
2775            }
2776            Self::MutationBatchStagedBytesExceeded => {
2777                Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2778                    boundary:
2779                        diagnostic_code::RuntimeBoundaryCode::MutationBatchStagedBytesExceeded,
2780                })
2781            }
2782            Self::MutationBatchResultBytesExceeded => {
2783                Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2784                    boundary:
2785                        diagnostic_code::RuntimeBoundaryCode::MutationBatchResultBytesExceeded,
2786                })
2787            }
2788            Self::MutationBatchEntityMismatch => {
2789                Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2790                    boundary: diagnostic_code::RuntimeBoundaryCode::MutationBatchEntityMismatch,
2791                })
2792            }
2793            Self::MutationBatchDuplicateKey => {
2794                Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2795                    boundary: diagnostic_code::RuntimeBoundaryCode::MutationBatchDuplicateKey,
2796                })
2797            }
2798            Self::MutationManagedTimestampRegression => {
2799                Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2800                    boundary:
2801                        diagnostic_code::RuntimeBoundaryCode::MutationManagedTimestampRegression,
2802                })
2803            }
2804            Self::AcceptedRowConstraintProgramCorrupt => {
2805                Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2806                    boundary:
2807                        diagnostic_code::RuntimeBoundaryCode::AcceptedRowConstraintProgramCorrupt,
2808                })
2809            }
2810        }
2811    }
2812
2813    /// Project safe mutation detail into canonical public numeric facts.
2814    #[must_use]
2815    #[cold]
2816    #[inline(never)]
2817    pub const fn diagnostic_facts(&self) -> Vec<(diagnostic_code::DiagnosticFactTag, u64)> {
2818        Vec::new()
2819    }
2820}
2821
2822impl RecoveryErrorDetail {
2823    /// Return the compact diagnostic code for this recovery detail.
2824    #[must_use]
2825    pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2826        match self {
2827            Self::UnsupportedFormatVersion { .. } => {
2828                diagnostic_code::DiagnosticCode::RuntimeIncompatiblePersistedFormat
2829            }
2830            Self::MalformedFormatMarker { .. } => {
2831                diagnostic_code::DiagnosticCode::RuntimeCorruption
2832            }
2833        }
2834    }
2835
2836    /// Return compact structured diagnostic detail for this recovery detail.
2837    #[must_use]
2838    pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2839        let kind = match self {
2840            Self::UnsupportedFormatVersion { .. } => {
2841                diagnostic_code::RuntimeErrorKind::IncompatiblePersistedFormat
2842            }
2843            Self::MalformedFormatMarker { .. } => diagnostic_code::RuntimeErrorKind::Corruption,
2844        };
2845
2846        Some(diagnostic_code::DiagnosticDetail::RuntimeKind { kind })
2847    }
2848
2849    /// Project database-format recovery context without retaining marker bytes.
2850    #[must_use]
2851    pub fn diagnostic_facts(&self) -> Vec<(diagnostic_code::DiagnosticFactTag, u64)> {
2852        match self {
2853            Self::UnsupportedFormatVersion { found, required } => {
2854                let mut facts = Vec::with_capacity(usize::from(found.is_some()) + 1);
2855                facts.push((
2856                    diagnostic_code::DiagnosticFactTag::ExpectedVersion,
2857                    u64::from(*required),
2858                ));
2859                if let Some(found) = found {
2860                    facts.push((
2861                        diagnostic_code::DiagnosticFactTag::ActualVersion,
2862                        u64::from(*found),
2863                    ));
2864                }
2865                facts
2866            }
2867            Self::MalformedFormatMarker { reason } => vec![(
2868                diagnostic_code::DiagnosticFactTag::DecodeReason,
2869                reason.diagnostic_decode_reason().raw(),
2870            )],
2871        }
2872    }
2873}
2874
2875impl StoreError {
2876    /// Return the compact diagnostic code for this store detail.
2877    #[must_use]
2878    pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2879        match self {
2880            Self::NotFound => diagnostic_code::DiagnosticCode::StoreNotFound,
2881            Self::Corrupt => diagnostic_code::DiagnosticCode::StoreCorruption,
2882            Self::InvariantViolation => diagnostic_code::DiagnosticCode::StoreInvariantViolation,
2883            Self::SchemaDdlPublicationRaceLost
2884            | Self::SchemaDdlRewriteRequiresMigration
2885            | Self::SchemaRowLayoutVersionExhausted
2886            | Self::SchemaTransitionBudgetExceeded { .. } => {
2887                diagnostic_code::DiagnosticCode::SchemaDdlAdmission
2888            }
2889            Self::JournalMutationRevisionExhausted | Self::SchemaGeneratedFieldAfterDdlField => {
2890                diagnostic_code::DiagnosticCode::RuntimeUnsupported
2891            }
2892            Self::SchemaGeneratedConstraintActivationStale => {
2893                diagnostic_code::DiagnosticCode::RuntimeConflict
2894            }
2895            Self::SchemaMigration { reason } => reason.diagnostic_code(),
2896        }
2897    }
2898
2899    /// Return compact structured diagnostic detail when the store error has one.
2900    #[must_use]
2901    pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2902        match self {
2903            Self::SchemaDdlPublicationRaceLost => {
2904                Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2905                    reason: diagnostic_code::SchemaDdlAdmissionCode::PublicationRaceLost,
2906                })
2907            }
2908            Self::SchemaDdlRewriteRequiresMigration => {
2909                Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2910                    reason: diagnostic_code::SchemaDdlAdmissionCode::SchemaRewriteRequiresMigration,
2911                })
2912            }
2913            Self::SchemaMigration { reason } => {
2914                Some(diagnostic_code::DiagnosticDetail::SchemaMigration { reason: *reason })
2915            }
2916            Self::SchemaRowLayoutVersionExhausted => {
2917                Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2918                    reason: diagnostic_code::SchemaDdlAdmissionCode::RowLayoutVersionExhausted,
2919                })
2920            }
2921            Self::JournalMutationRevisionExhausted => {
2922                Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2923                    boundary:
2924                        diagnostic_code::RuntimeBoundaryCode::JournalMutationRevisionExhausted,
2925                })
2926            }
2927            Self::SchemaTransitionBudgetExceeded { .. } => {
2928                Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
2929                    reason: diagnostic_code::SchemaDdlAdmissionCode::SchemaTransitionBudgetExceeded,
2930                })
2931            }
2932            Self::SchemaGeneratedFieldAfterDdlField => {
2933                Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2934                    boundary: diagnostic_code::RuntimeBoundaryCode::GeneratedFieldAfterDdlField,
2935                })
2936            }
2937            Self::SchemaGeneratedConstraintActivationStale => {
2938                Some(diagnostic_code::DiagnosticDetail::RuntimeBoundary {
2939                    boundary:
2940                        diagnostic_code::RuntimeBoundaryCode::GeneratedConstraintActivationStale,
2941                })
2942            }
2943            Self::NotFound | Self::Corrupt | Self::InvariantViolation => None,
2944        }
2945    }
2946}
2947
2948impl QueryErrorDetail {
2949    /// Return the compact diagnostic code for this query detail.
2950    #[must_use]
2951    pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
2952        match self {
2953            Self::NumericOverflow => diagnostic_code::DiagnosticCode::QueryNumericOverflow,
2954            Self::NumericNotRepresentable => {
2955                diagnostic_code::DiagnosticCode::QueryNumericNotRepresentable
2956            }
2957            Self::UnsupportedSqlFeature { .. } => {
2958                diagnostic_code::DiagnosticCode::QueryUnsupportedSqlFeature
2959            }
2960            Self::SqlLowering { .. } => diagnostic_code::DiagnosticCode::QueryUnsupportedSqlFeature,
2961            Self::UnsupportedProjection { .. } => {
2962                diagnostic_code::DiagnosticCode::QueryUnsupportedProjection
2963            }
2964            Self::UnknownAggregateTargetField => {
2965                diagnostic_code::DiagnosticCode::QueryUnknownAggregateTargetField
2966            }
2967            Self::ResultShapeMismatch { .. } => {
2968                diagnostic_code::DiagnosticCode::QueryResultShapeMismatch
2969            }
2970            Self::QueryReadAdmission { .. } => diagnostic_code::DiagnosticCode::QueryReadAdmission,
2971            Self::SqlSurfaceMismatch { .. } => {
2972                diagnostic_code::DiagnosticCode::QuerySqlSurfaceMismatch
2973            }
2974            Self::SqlWriteBoundary { .. } => diagnostic_code::DiagnosticCode::QuerySqlWriteBoundary,
2975            Self::SchemaDdlAdmission { .. } => diagnostic_code::DiagnosticCode::SchemaDdlAdmission,
2976            Self::StaleSchemaRevision => diagnostic_code::DiagnosticCode::RuntimeConflict,
2977        }
2978    }
2979
2980    /// Return compact structured diagnostic detail when the query detail has one.
2981    #[must_use]
2982    pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
2983        match self {
2984            Self::UnsupportedSqlFeature { feature } => {
2985                Some(diagnostic_code::DiagnosticDetail::UnsupportedSqlFeature { feature: *feature })
2986            }
2987            Self::SqlLowering { reason } => {
2988                Some(diagnostic_code::DiagnosticDetail::SqlLowering { reason: *reason })
2989            }
2990            Self::UnsupportedProjection { reason } => {
2991                Some(diagnostic_code::DiagnosticDetail::QueryProjection { reason: *reason })
2992            }
2993            Self::ResultShapeMismatch { reason } => {
2994                Some(diagnostic_code::DiagnosticDetail::QueryResultShape { reason: *reason })
2995            }
2996            Self::QueryReadAdmission { reason } => {
2997                Some(diagnostic_code::DiagnosticDetail::QueryReadAdmission { reason: *reason })
2998            }
2999            Self::SqlSurfaceMismatch { mismatch } => {
3000                Some(diagnostic_code::DiagnosticDetail::SqlSurfaceMismatch {
3001                    mismatch: *mismatch,
3002                })
3003            }
3004            Self::SqlWriteBoundary { boundary } => {
3005                Some(diagnostic_code::DiagnosticDetail::SqlWriteBoundary {
3006                    boundary: *boundary,
3007                })
3008            }
3009            Self::SchemaDdlAdmission { error } => {
3010                Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
3011                    reason: error.diagnostic_code(),
3012                })
3013            }
3014            Self::NumericOverflow
3015            | Self::NumericNotRepresentable
3016            | Self::UnknownAggregateTargetField
3017            | Self::StaleSchemaRevision => None,
3018        }
3019    }
3020
3021    /// Project safe query detail into canonical public numeric facts.
3022    #[must_use]
3023    #[cold]
3024    #[inline(never)]
3025    pub const fn diagnostic_facts(&self) -> Vec<(diagnostic_code::DiagnosticFactTag, u64)> {
3026        Vec::new()
3027    }
3028}
3029
3030impl SchemaDdlAdmissionError {
3031    /// Return the compact diagnostic code for this SQL DDL admission reason.
3032    #[must_use]
3033    pub const fn diagnostic_code(&self) -> diagnostic_code::SchemaDdlAdmissionCode {
3034        match self {
3035            Self::MissingExpectedSchemaVersion => {
3036                diagnostic_code::SchemaDdlAdmissionCode::MissingExpectedSchemaVersion
3037            }
3038            Self::MissingNextSchemaVersion => {
3039                diagnostic_code::SchemaDdlAdmissionCode::MissingNextSchemaVersion
3040            }
3041            Self::StaleExpectedSchemaVersion => {
3042                diagnostic_code::SchemaDdlAdmissionCode::StaleExpectedSchemaVersion
3043            }
3044            Self::InvalidExpectedSchemaVersion => {
3045                diagnostic_code::SchemaDdlAdmissionCode::InvalidExpectedSchemaVersion
3046            }
3047            Self::InvalidNextSchemaVersion => {
3048                diagnostic_code::SchemaDdlAdmissionCode::InvalidNextSchemaVersion
3049            }
3050            Self::AcceptedSchemaChangeWithoutVersionBump => {
3051                diagnostic_code::SchemaDdlAdmissionCode::AcceptedSchemaChangeWithoutVersionBump
3052            }
3053            Self::EmptyVersionBump => diagnostic_code::SchemaDdlAdmissionCode::EmptyVersionBump,
3054            Self::VersionGap => diagnostic_code::SchemaDdlAdmissionCode::VersionGap,
3055            Self::VersionRollback => diagnostic_code::SchemaDdlAdmissionCode::VersionRollback,
3056            Self::FingerprintMethodMismatch => {
3057                diagnostic_code::SchemaDdlAdmissionCode::FingerprintMethodMismatch
3058            }
3059            Self::UnsupportedTransitionClass => {
3060                diagnostic_code::SchemaDdlAdmissionCode::UnsupportedTransitionClass
3061            }
3062            Self::PhysicalRunnerMissing => {
3063                diagnostic_code::SchemaDdlAdmissionCode::PhysicalRunnerMissing
3064            }
3065            Self::ValidationFailed => diagnostic_code::SchemaDdlAdmissionCode::ValidationFailed,
3066            Self::PublicationRaceLost => {
3067                diagnostic_code::SchemaDdlAdmissionCode::PublicationRaceLost
3068            }
3069            Self::InvalidAddColumnDefault => {
3070                diagnostic_code::SchemaDdlAdmissionCode::InvalidAddColumnDefault
3071            }
3072            Self::InvalidAlterColumnDefault => {
3073                diagnostic_code::SchemaDdlAdmissionCode::InvalidAlterColumnDefault
3074            }
3075            Self::GeneratedIndexDropRejected => {
3076                diagnostic_code::SchemaDdlAdmissionCode::GeneratedIndexDropRejected
3077            }
3078            Self::SchemaRewriteRequiresMigration => {
3079                diagnostic_code::SchemaDdlAdmissionCode::SchemaRewriteRequiresMigration
3080            }
3081            Self::SchemaTransitionBudgetExceeded { .. } => {
3082                diagnostic_code::SchemaDdlAdmissionCode::SchemaTransitionBudgetExceeded
3083            }
3084            Self::GeneratedFieldDefaultChangeRejected => {
3085                diagnostic_code::SchemaDdlAdmissionCode::GeneratedFieldDefaultChangeRejected
3086            }
3087            Self::GeneratedFieldNullabilityChangeRejected => {
3088                diagnostic_code::SchemaDdlAdmissionCode::GeneratedFieldNullabilityChangeRejected
3089            }
3090            Self::RowLayoutVersionExhausted => {
3091                diagnostic_code::SchemaDdlAdmissionCode::RowLayoutVersionExhausted
3092            }
3093        }
3094    }
3095}
3096
3097///
3098/// ErrorClass
3099/// Internal error taxonomy for runtime classification.
3100/// Not a stable API; may change without notice.
3101///
3102
3103#[repr(u8)]
3104#[derive(Clone, Copy, Eq, PartialEq)]
3105pub enum ErrorClass {
3106    Corruption,
3107    IncompatiblePersistedFormat,
3108    NotFound,
3109    Internal,
3110    Conflict,
3111    Unsupported,
3112    InvariantViolation,
3113}
3114
3115impl ErrorClass {
3116    /// Return a compact diagnostic code for this broad class and origin pair.
3117    #[must_use]
3118    pub const fn diagnostic_code(self, origin: ErrorOrigin) -> diagnostic_code::DiagnosticCode {
3119        match self {
3120            Self::Corruption if matches!(origin, ErrorOrigin::Store) => {
3121                diagnostic_code::DiagnosticCode::StoreCorruption
3122            }
3123            Self::Corruption => diagnostic_code::DiagnosticCode::RuntimeCorruption,
3124            Self::IncompatiblePersistedFormat => {
3125                diagnostic_code::DiagnosticCode::RuntimeIncompatiblePersistedFormat
3126            }
3127            Self::NotFound if matches!(origin, ErrorOrigin::Store) => {
3128                diagnostic_code::DiagnosticCode::StoreNotFound
3129            }
3130            Self::NotFound => diagnostic_code::DiagnosticCode::RuntimeNotFound,
3131            Self::Internal => diagnostic_code::DiagnosticCode::RuntimeInternal,
3132            Self::Conflict => diagnostic_code::DiagnosticCode::RuntimeConflict,
3133            Self::Unsupported if matches!(origin, ErrorOrigin::Cursor) => {
3134                diagnostic_code::DiagnosticCode::QueryInvalidContinuationCursor
3135            }
3136            Self::Unsupported => diagnostic_code::DiagnosticCode::RuntimeUnsupported,
3137            Self::InvariantViolation if matches!(origin, ErrorOrigin::Store) => {
3138                diagnostic_code::DiagnosticCode::StoreInvariantViolation
3139            }
3140            Self::InvariantViolation => diagnostic_code::DiagnosticCode::RuntimeInvariantViolation,
3141        }
3142    }
3143}
3144
3145impl fmt::Debug for ErrorClass {
3146    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3147        write!(f, "{}", *self as u8)
3148    }
3149}
3150
3151///
3152/// ErrorOrigin
3153/// Internal origin taxonomy for runtime classification.
3154/// Not a stable API; may change without notice.
3155///
3156
3157#[repr(u8)]
3158#[derive(Clone, Copy, Eq, PartialEq)]
3159pub enum ErrorOrigin {
3160    Serialize,
3161    Store,
3162    Index,
3163    Identity,
3164    Query,
3165    Planner,
3166    Cursor,
3167    Recovery,
3168    Response,
3169    Executor,
3170    Interface,
3171}
3172
3173impl ErrorOrigin {
3174    /// Return the compact diagnostic origin for this internal origin.
3175    #[must_use]
3176    pub const fn diagnostic_origin(self) -> diagnostic_code::ErrorOrigin {
3177        match self {
3178            Self::Serialize => diagnostic_code::ErrorOrigin::Serialize,
3179            Self::Store => diagnostic_code::ErrorOrigin::Store,
3180            Self::Index => diagnostic_code::ErrorOrigin::Index,
3181            Self::Identity => diagnostic_code::ErrorOrigin::Identity,
3182            Self::Query => diagnostic_code::ErrorOrigin::Query,
3183            Self::Planner => diagnostic_code::ErrorOrigin::Planner,
3184            Self::Cursor => diagnostic_code::ErrorOrigin::Cursor,
3185            Self::Recovery => diagnostic_code::ErrorOrigin::Recovery,
3186            Self::Response => diagnostic_code::ErrorOrigin::Response,
3187            Self::Executor => diagnostic_code::ErrorOrigin::Executor,
3188            Self::Interface => diagnostic_code::ErrorOrigin::Interface,
3189        }
3190    }
3191}
3192
3193impl fmt::Debug for ErrorOrigin {
3194    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3195        write!(f, "{}", *self as u8)
3196    }
3197}