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>;