derec_library/protocol/error.rs
1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2026 DeRec Alliance. All rights reserved.
3
4use super::SecretKind;
5use crate::types::ChannelId;
6
7/// Error returned by [`DeRecProtocol::process`](super::DeRecProtocol::process).
8///
9/// Wraps the underlying [`crate::Error`] with the `channel_id` extracted from
10/// the inbound message envelope, so consumers always know which channel
11/// produced the error.
12///
13/// `channel_id` is `None` only when the envelope itself could not be decoded
14/// (i.e. the raw bytes are not a valid protobuf `DeRecMessage`).
15#[derive(Debug, thiserror::Error)]
16#[error("{source}")]
17pub struct ProcessError {
18 /// The channel that produced the error, if the envelope was decodable.
19 pub channel_id: Option<ChannelId>,
20 /// The underlying error.
21 #[source]
22 pub source: crate::Error,
23}
24
25impl ProcessError {
26 /// Convenience: extract `(status, memo)` if the underlying error is a
27 /// `NonOkStatus` from any primitive.
28 pub fn as_non_ok_status(&self) -> Option<(i32, &str)> {
29 self.source.as_non_ok_status()
30 }
31}
32
33/// Errors produced by [`DeRecSecretStore`](super::DeRecSecretStore) implementations.
34///
35/// Individual Verifiable Secret Sharing shares are information-theoretically
36/// secure, so "secret" here refers only to [`SharedKey`](crate::types::SharedKey) and
37/// [`PairingKeyMaterial`](super::PairingKeyMaterial)
38/// — the two kinds of data stored in this trait.
39#[derive(Debug, thiserror::Error)]
40#[non_exhaustive]
41pub enum SecretStoreError {
42 /// An I/O or serialization error in the underlying storage backend.
43 ///
44 /// Used when the implementation cannot categorise the failure more
45 /// precisely (e.g., a file-system error, an SQLite constraint, or a
46 /// serialization failure).
47 ///
48 /// The original error is preserved as the `source` so that callers can
49 /// inspect the full error chain via [`std::error::Error::source`].
50 #[error("secret store backend error")]
51 Backend(#[source] Box<dyn std::error::Error + Send + Sync + 'static>),
52
53 /// Returned by [`super::DeRecSecretStore::load_many`] when one or more
54 /// requested channels have no stored secret of the requested
55 /// [`SecretKind`] and the caller requested
56 /// [`super::MissingPolicy::Fail`].
57 ///
58 /// `channel_ids` carries the raw u64 ids of channels that came back empty;
59 /// the protocol orchestrator logs them at `error!` level and surfaces
60 /// the same list to consumers.
61 #[error("secret store: missing {kind:?} entries for channel(s): {channel_ids:?}")]
62 MissingEntries {
63 kind: SecretKind,
64 channel_ids: Vec<u64>,
65 },
66}
67
68/// Errors produced by [`DeRecChannelStore`](super::DeRecChannelStore) implementations.
69#[derive(Debug, thiserror::Error)]
70#[non_exhaustive]
71pub enum ChannelStoreError {
72 /// A channel with the given `channel_id` already exists.
73 #[error("channel already exists for {channel_id}")]
74 AlreadyExists { channel_id: u64 },
75
76 /// No channel was found for the given `channel_id`.
77 #[error("channel not found for {channel_id}")]
78 NotFound { channel_id: u64 },
79
80 /// An I/O or serialization error in the underlying storage backend.
81 #[error("channel store backend error")]
82 Backend(#[source] Box<dyn std::error::Error + Send + Sync + 'static>),
83}
84
85/// Errors produced by [`DeRecStateStore`](super::DeRecStateStore) implementations.
86///
87/// The state store holds in-flight orchestrator state (outstanding
88/// verification challenges, in-progress recovery accumulators, pending unpair
89/// acknowledgements) so that stateless or load-balanced deployments do not
90/// lose it across process restarts.
91#[derive(Debug, thiserror::Error)]
92#[non_exhaustive]
93pub enum StateStoreError {
94 /// An I/O or serialization error in the underlying storage backend.
95 ///
96 /// The original error is preserved as the `source` so that callers can
97 /// inspect the full error chain via [`std::error::Error::source`].
98 #[error("state store backend error")]
99 Backend(#[source] Box<dyn std::error::Error + Send + Sync + 'static>),
100}
101
102/// Errors produced by [`DeRecShareStore`](super::DeRecShareStore) implementations.
103#[derive(Debug, thiserror::Error)]
104#[non_exhaustive]
105pub enum ShareStoreError {
106 /// A share for `(channel_id, version)` already exists.
107 ///
108 /// Returned by [`DeRecShareStore::save`](super::DeRecShareStore::save) when the
109 /// implementation enforces immutability of versioned share slots. The protocol treats each
110 /// `(channel_id, version)` pair as write-once; overwriting a confirmed share
111 /// is a protocol violation.
112 #[error("share already exists for channel {channel_id} version {version}")]
113 AlreadyExists { channel_id: u64, version: u32 },
114
115 /// No share was found for `(channel_id, version)`.
116 ///
117 /// Implementations that prefer an explicit error over returning `Ok(None)`
118 /// may return this variant from [`DeRecShareStore::load`](super::DeRecShareStore::load).
119 #[error("share not found for channel {channel_id} version {version}")]
120 NotFound { channel_id: u64, version: u32 },
121
122 /// An I/O or serialization error in the underlying storage backend.
123 ///
124 /// The original error is preserved as the `source` so that callers can
125 /// inspect the full error chain via [`std::error::Error::source`].
126 #[error("share store backend error")]
127 Backend(#[source] Box<dyn std::error::Error + Send + Sync + 'static>),
128}