nodedb_cluster/mirror/error.rs
1// SPDX-License-Identifier: BUSL-1.1
2
3//! Error types for cross-cluster mirror transport and bootstrap.
4
5use thiserror::Error;
6
7/// Errors produced by cross-cluster mirror operations.
8///
9/// These wrap into [`crate::error::ClusterError::Mirror`] at the public
10/// boundary so callers have a single error type to handle.
11#[derive(Debug, Error)]
12pub enum MirrorError {
13 /// The remote cluster refused our connection because the `source_cluster`
14 /// we declared does not match their own cluster id.
15 #[error(
16 "cluster-id mismatch: we declared source_cluster={declared:?}, \
17 remote reports its id as {remote:?}"
18 )]
19 ClusterIdMismatch { declared: String, remote: String },
20
21 /// The remote cluster rejected the mirror link because the connecting
22 /// peer presented `Observer` role credentials but tried to perform a
23 /// voter operation (vote request, conf change, etc.).
24 #[error("observer-role violation: peer attempted voter operation: {detail}")]
25 ObserverRoleViolation { detail: String },
26
27 /// Snapshot transfer was aborted because a chunk arrived out of order.
28 ///
29 /// The receiver resets and requests a fresh snapshot from the source.
30 #[error(
31 "snapshot offset regression for database {database_id:?}: \
32 expected {expected}, got {actual}"
33 )]
34 SnapshotOffsetRegression {
35 database_id: String,
36 expected: u64,
37 actual: u64,
38 },
39
40 /// Snapshot CRC validation failed at the final chunk.
41 #[error(
42 "snapshot CRC mismatch for database {database_id:?}: \
43 stored {stored:#010x}, computed {computed:#010x}"
44 )]
45 SnapshotCrcMismatch {
46 database_id: String,
47 stored: u32,
48 computed: u32,
49 },
50
51 /// The cross-cluster handshake wire message could not be decoded.
52 #[error("cross-cluster handshake codec error: {detail}")]
53 HandshakeCodec { detail: String },
54
55 /// The mirror declared a wire protocol version the source does not
56 /// implement (or vice versa). Surfaced immediately without retry — the
57 /// peers must be upgraded in lockstep.
58 #[error("cross-cluster protocol version mismatch: local={local}, remote_detail={detail:?}")]
59 ProtocolVersionMismatch { local: u16, detail: String },
60
61 /// QUIC transport error during cross-cluster operations.
62 #[error("cross-cluster transport error: {detail}")]
63 Transport { detail: String },
64
65 /// Observer-side bytes-in-flight cap was exceeded; the source should
66 /// pause sending until the observer drains.
67 #[error(
68 "bytes-in-flight cap exceeded: in_flight={in_flight}, cap={cap} for mirror {database_id:?}"
69 )]
70 BytesInFlightCapExceeded {
71 database_id: String,
72 in_flight: u64,
73 cap: u64,
74 },
75
76 /// The mirror is in `Promoted` state and can no longer accept replication.
77 #[error("mirror {database_id:?} is promoted and no longer accepts replication")]
78 MirrorPromoted { database_id: String },
79}