grafos_std/error.rs
1//! Error types for fabric resource operations.
2//!
3//! All fallible operations in grafos-std return [`Result<T>`], which is an
4//! alias for `core::result::Result<T, FabricError>`. The [`FabricError`]
5//! enum maps directly to the status codes returned by FBMU/FBBU host
6//! functions.
7
8use core::fmt;
9
10/// Errors returned by fabric resource operations.
11///
12/// Each variant corresponds to a well-defined failure mode in the fabricBIOS
13/// host API. The host functions return integer status codes which are
14/// translated into these variants by `FabricError::from_status`.
15///
16/// # Status code mapping
17///
18/// | Code | Variant |
19/// |------|---------|
20/// | 0 | Success (no error) |
21/// | -1 | [`Disconnected`](FabricError::Disconnected) |
22/// | -2 | [`LeaseExpired`](FabricError::LeaseExpired) |
23/// | -3 | [`Fenced`](FabricError::Fenced) |
24/// | -4 | [`CapacityExceeded`](FabricError::CapacityExceeded) |
25/// | -5 | [`Unsupported`](FabricError::Unsupported) |
26/// | -6 | [`Revoked`](FabricError::Revoked) |
27/// | other | [`IoError(code)`](FabricError::IoError) |
28#[derive(Debug, Clone, PartialEq, Eq)]
29pub enum FabricError {
30 /// The lease for this resource has expired.
31 ///
32 /// Returned when an operation targets a resource whose lease has timed
33 /// out at the control-plane level. The resource may have been reclaimed
34 /// by the node.
35 LeaseExpired,
36
37 /// The lease was explicitly revoked.
38 ///
39 /// Returned when the resource's lease has been forcibly revoked by the
40 /// control plane (e.g. via REVOKE_BROADCAST, preemption, or WITHDRAW).
41 /// Unlike `LeaseExpired`, this is non-recoverable — the resource was
42 /// taken, not timed out.
43 Revoked,
44
45 /// The requested resource exceeds available capacity.
46 ///
47 /// Returned by builder `.acquire()` methods when the node cannot satisfy
48 /// the minimum capacity constraint, or by block I/O when the LBA is
49 /// out of range.
50 CapacityExceeded,
51
52 /// The resource has been fenced due to a teardown failure.
53 ///
54 /// A fenced resource cannot accept new leases. This is a terminal state
55 /// in the fabricBIOS lease model — the node detected that data-plane
56 /// teardown did not complete cleanly and has locked the resource to
57 /// prevent data corruption.
58 Fenced,
59
60 /// The connection to the remote node was lost.
61 ///
62 /// Indicates a transport-level failure (QUIC connection closed, network
63 /// timeout, or node crash). Retrying with a new connection may succeed
64 /// if the node recovers.
65 Disconnected,
66
67 /// An I/O error with a host-specific status code.
68 ///
69 /// Wraps any status code not covered by the well-known variants above.
70 /// The inner `i32` is the raw status code returned by the host function.
71 IoError(i32),
72
73 /// The requested operation is not supported.
74 ///
75 /// Returned by GPU and CPU modules whose host functions are not yet
76 /// implemented, or by nodes that do not expose the requested resource
77 /// type.
78 Unsupported,
79
80 /// A GPU session operation failed on the daemon side.
81 ///
82 /// The inner `u8` carries the raw
83 /// `fabricbios_core::gpu_session::SESSION_STATUS_*` code
84 /// (e.g. `SESSION_STATUS_INVALID_HANDLE = 3`,
85 /// `SESSION_STATUS_NO_CONTEXT = 2`). Positive, non-zero status values
86 /// returned by the `fabricbios_gpu_v1` hostcalls surface as this
87 /// variant; transport- and lease-level failures still map to the
88 /// existing [`FabricError`] variants via [`FabricError::from_status`].
89 GpuSessionFailed(u8),
90}
91
92impl fmt::Display for FabricError {
93 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
94 match self {
95 FabricError::LeaseExpired => write!(f, "lease expired"),
96 FabricError::Revoked => write!(f, "lease revoked"),
97 FabricError::CapacityExceeded => write!(f, "capacity exceeded"),
98 FabricError::Fenced => write!(f, "resource fenced"),
99 FabricError::Disconnected => write!(f, "disconnected"),
100 FabricError::IoError(code) => write!(f, "I/O error (status {code})"),
101 FabricError::Unsupported => write!(f, "unsupported"),
102 FabricError::GpuSessionFailed(code) => {
103 write!(f, "GPU session op failed (SESSION_STATUS_{code})")
104 }
105 }
106 }
107}
108
109#[cfg(feature = "std")]
110impl std::error::Error for FabricError {}
111
112/// Alias for `core::result::Result<T, FabricError>`.
113///
114/// This is the return type for all fallible operations in grafos-std.
115pub type Result<T> = core::result::Result<T, FabricError>;
116
117impl FabricError {
118 /// Convert a host function status code to a `FabricError`.
119 ///
120 /// Status 0 is success and returns `None`. Negative values map to
121 /// specific error variants as documented on [`FabricError`].
122 pub(crate) fn from_status(status: i32) -> Option<FabricError> {
123 match status {
124 0 => None,
125 -1 => Some(FabricError::Disconnected),
126 -2 => Some(FabricError::LeaseExpired),
127 -3 => Some(FabricError::Fenced),
128 -4 => Some(FabricError::CapacityExceeded),
129 -5 => Some(FabricError::Unsupported),
130 -6 => Some(FabricError::Revoked),
131 other => Some(FabricError::IoError(other)),
132 }
133 }
134}