Skip to main content

clawft_kernel/
error.rs

1//! Kernel error types.
2//!
3//! All kernel operations return [`KernelError`] for typed error
4//! handling. The error variants cover process table operations,
5//! service lifecycle, IPC, and boot sequence failures.
6
7use crate::process::ProcessState;
8
9/// Kernel-level errors.
10#[non_exhaustive]
11#[derive(Debug, thiserror::Error)]
12pub enum KernelError {
13    /// Process not found in the process table.
14    #[error("process not found: PID {pid}")]
15    ProcessNotFound {
16        /// The PID that was looked up.
17        pid: u64,
18    },
19
20    /// Invalid process state transition.
21    #[error("invalid state transition for PID {pid}: {from} -> {to}")]
22    InvalidStateTransition {
23        /// The affected PID.
24        pid: u64,
25        /// Current state.
26        from: ProcessState,
27        /// Requested state.
28        to: ProcessState,
29    },
30
31    /// Process table has reached maximum capacity.
32    #[error("process table full (max: {max})")]
33    ProcessTableFull {
34        /// Maximum number of processes allowed.
35        max: u32,
36    },
37
38    /// Service-related error.
39    #[error("service error: {0}")]
40    Service(String),
41
42    /// Boot sequence error.
43    #[error("boot error: {0}")]
44    Boot(String),
45
46    /// Boot refused for a reason retrying cannot fix (chain lock held,
47    /// legacy chain adoption refused, unusable boot configuration). The
48    /// daemon exits 78 on this so service managers do not restart-loop it.
49    #[error("boot refused: {0}")]
50    BootRefused(String),
51
52    /// IPC / messaging error.
53    #[error("ipc error: {0}")]
54    Ipc(String),
55
56    /// IPC frame exceeded the configured maximum payload size.
57    #[error("ipc message too large: {size} bytes (limit {limit} bytes)")]
58    MessageTooLarge {
59        /// Observed serialized size in bytes.
60        size: usize,
61        /// Configured limit in bytes (16 MiB by default).
62        limit: usize,
63    },
64
65    /// Kernel is in wrong state for requested operation.
66    #[error("kernel state error: expected {expected}, got {actual}")]
67    WrongState {
68        /// Expected state.
69        expected: String,
70        /// Actual state.
71        actual: String,
72    },
73
74    /// Capability check denied an action.
75    #[error("capability denied for PID {pid}: cannot {action} -- {reason}")]
76    CapabilityDenied {
77        /// The PID of the process that was denied.
78        pid: u64,
79        /// The action that was attempted.
80        action: String,
81        /// Why the action was denied.
82        reason: String,
83    },
84
85    /// Resource limit exceeded.
86    #[error("resource limit exceeded for PID {pid}: {resource} ({current} > {limit})")]
87    ResourceLimitExceeded {
88        /// The PID of the process.
89        pid: u64,
90        /// Name of the resource (memory, cpu_time, etc.).
91        resource: String,
92        /// Current usage value.
93        current: u64,
94        /// Configured limit.
95        limit: u64,
96    },
97
98    /// Agent spawn failed.
99    #[error("spawn failed for agent '{agent_id}': {reason}")]
100    SpawnFailed {
101        /// The agent that was being spawned.
102        agent_id: String,
103        /// Why the spawn failed.
104        reason: String,
105    },
106
107    /// Spawn backend not available (defined but not yet implemented).
108    #[error("backend not available: {backend} ({reason})")]
109    BackendNotAvailable {
110        /// The backend that was requested.
111        backend: String,
112        /// Why the backend is not available.
113        reason: String,
114    },
115
116    /// Operation timed out.
117    #[error("timeout: {operation} after {duration_ms}ms")]
118    Timeout {
119        /// Description of the operation that timed out.
120        operation: String,
121        /// How long we waited before timing out.
122        duration_ms: u64,
123    },
124
125    /// Configuration error.
126    #[error("config error: {0}")]
127    Config(String),
128
129    /// Disk quota exceeded (K1-G4).
130    #[cfg(feature = "os-patterns")]
131    #[error("disk quota exceeded for agent '{agent_id}': {current_bytes} > {limit_bytes} bytes")]
132    QuotaExceeded {
133        /// Agent that exceeded its quota.
134        agent_id: String,
135        /// Current disk usage.
136        current_bytes: u64,
137        /// Configured limit.
138        limit_bytes: u64,
139    },
140
141    /// Governance gate denied the action.
142    #[cfg(feature = "exochain")]
143    #[error("governance denied: {0}")]
144    GovernanceDenied(String),
145
146    /// Mesh networking error.
147    #[error("mesh error: {0}")]
148    Mesh(String),
149
150    /// Wraps a generic error from downstream crates.
151    #[error(transparent)]
152    Other(#[from] Box<dyn std::error::Error + Send + Sync>),
153}
154
155/// Convenience alias for kernel results.
156pub type KernelResult<T> = Result<T, KernelError>;