post_cortex_storage/error.rs
1// Copyright (c) 2025, 2026 Julius ML
2// Licensed under the MIT License. See LICENSE at the workspace root.
3
4//! Typed error hierarchy for `post-cortex-storage`.
5//!
6//! See the crate-level docs on `post-cortex-core::error` for the
7//! workspace-wide error policy. Storage errors carry source chains via
8//! `#[source]` so callers can pattern-match on the underlying RocksDB /
9//! SurrealDB cause.
10
11use thiserror::Error;
12
13/// Errors produced by storage backends.
14#[derive(Debug, Error)]
15pub enum Error {
16 /// RocksDB-layer error (transaction, write batch, iterator, column
17 /// family).
18 #[error("rocksdb error: {0}")]
19 RocksDb(#[from] rocksdb::Error),
20
21 /// SurrealDB error (kv-mem / kv-tikv / protocol-ws).
22 #[cfg(feature = "surrealdb-storage")]
23 #[error("surrealdb error: {0}")]
24 SurrealDb(String),
25
26 /// (De)serialization failure on a persisted record.
27 #[error("serialization error: {0}")]
28 Serialization(String),
29
30 /// Logical "not found" — referenced session / workspace / entity
31 /// missing from the backend.
32 #[error("not found: {kind} {id}")]
33 NotFound {
34 /// Kind of entity that was missing (e.g. `"session"`, `"workspace"`).
35 kind: &'static str,
36 /// Identifier of the missing entity.
37 id: String,
38 },
39
40 /// Export / import file format error (corrupt header, unsupported
41 /// version, compression failure).
42 #[error("export/import format error: {0}")]
43 Format(String),
44
45 /// I/O error from the underlying filesystem.
46 #[error("io error: {0}")]
47 Io(#[from] std::io::Error),
48
49 /// Catch-all for migrating call sites that still use `anyhow`.
50 #[error(transparent)]
51 External(#[from] anyhow::Error),
52}
53
54/// Crate-level result alias.
55pub type Result<T, E = Error> = std::result::Result<T, E>;
56
57// bincode 2 conversions
58impl From<bincode::error::EncodeError> for Error {
59 fn from(err: bincode::error::EncodeError) -> Self {
60 Self::Serialization(err.to_string())
61 }
62}
63
64impl From<bincode::error::DecodeError> for Error {
65 fn from(err: bincode::error::DecodeError) -> Self {
66 Self::Serialization(err.to_string())
67 }
68}
69
70impl Error {
71 /// A stable discriminant for metrics / structured logs.
72 #[must_use]
73 pub fn kind(&self) -> &'static str {
74 match self {
75 Self::RocksDb(_) => "rocksdb",
76 #[cfg(feature = "surrealdb-storage")]
77 Self::SurrealDb(_) => "surrealdb",
78 Self::Serialization(_) => "serialization",
79 Self::NotFound { .. } => "not_found",
80 Self::Format(_) => "format",
81 Self::Io(_) => "io",
82 Self::External(_) => "external",
83 }
84 }
85}