cortex_core/error.rs
1//! Pure-typing errors for `cortex-core`.
2//!
3//! These errors describe **shape** and **typing** failures: an ID string that
4//! cannot be parsed, a serialized record whose `schema_version` does not match
5//! what this build understands, a JSON value that fails structural validation.
6//!
7//! `cortex-core` performs **no I/O** (per BUILD_SPEC §8). Surface I/O failures
8//! at the crate boundary that owns them (`cortex-ledger`, `cortex-store`, …)
9//! by composing them with `CoreError` via the usual `From` wiring; do **not**
10//! add I/O variants here.
11
12use thiserror::Error;
13
14/// Errors raised by `cortex-core` parsing and validation.
15#[derive(Debug, Error, Clone, PartialEq, Eq)]
16pub enum CoreError {
17 /// A string failed to parse as a prefix-ULID identifier.
18 ///
19 /// Either the prefix did not match the expected variant (e.g. `trc_…`
20 /// passed where `evt_…` was required) or the ULID body was malformed.
21 #[error("id parse error: {0}")]
22 IdParse(String),
23
24 /// A persisted record was decoded with an unexpected `schema_version`.
25 ///
26 /// Producers MUST refuse to operate on records whose schema is newer than
27 /// they understand; consumers MAY upcast older records via documented
28 /// migrations. See [`crate::SCHEMA_VERSION`].
29 #[error("schema version mismatch: found {found}, expected {expected}")]
30 SchemaMismatch {
31 /// The version observed on the wire / in storage.
32 found: u16,
33 /// The version this build of `cortex-core` understands.
34 expected: u16,
35 },
36
37 /// A JSON value failed structural validation (missing field, wrong type,
38 /// constraint violation). The contained string is operator-facing detail.
39 #[error("json validation failed: {0}")]
40 JsonValidation(String),
41
42 /// Generic value-shape validation failure (non-JSON contexts: invariants,
43 /// pre-conditions on typed values).
44 ///
45 /// Prefer [`CoreError::JsonValidation`] for failures that originated in a
46 /// JSON decode / schema check.
47 #[error("validation failed: {0}")]
48 Validation(String),
49}
50
51/// Crate-wide `Result` alias.
52pub type CoreResult<T> = Result<T, CoreError>;
53
54/// Backwards-compat alias for the pre-Lane-1.A error name.
55///
56/// Other crates in the workspace still reference `cortex_core::CortexError`;
57/// keep this alias available until they are migrated to [`CoreError`] in a
58/// follow-up lane. **New code MUST use [`CoreError`] directly.** When all
59/// downstream call sites have moved over, drop this alias in a single PR
60/// alongside a `SCHEMA_VERSION` non-bump (this is an API rename, not a wire
61/// rename).
62pub use CoreError as CortexError;
63
64/// Backwards-compat alias for the pre-Lane-1.A `Result` alias.
65///
66/// See the migration note on [`CortexError`]. **New code MUST use
67/// [`CoreResult`] directly.**
68pub type CortexResult<T> = CoreResult<T>;
69
70#[cfg(test)]
71mod tests {
72 use super::*;
73
74 #[test]
75 fn schema_mismatch_renders_clean_message() {
76 let e = CoreError::SchemaMismatch {
77 found: 2,
78 expected: 1,
79 };
80 assert_eq!(
81 e.to_string(),
82 "schema version mismatch: found 2, expected 1"
83 );
84 }
85
86 #[test]
87 fn id_parse_renders_clean_message() {
88 let e = CoreError::IdParse("bad".into());
89 assert_eq!(e.to_string(), "id parse error: bad");
90 }
91}