mlua_swarm/core/errors.rs
1//! Engine error type.
2
3use crate::types::{Role, Verb};
4use thiserror::Error;
5
6/// All ways an engine operation can fail.
7#[derive(Debug, Error)]
8pub enum EngineError {
9 /// A required lock was busy and the operation gave up without retrying.
10 #[error("lock busy ({0})")]
11 LockBusy(&'static str),
12
13 /// A required lock was still busy after the configured retry budget was
14 /// exhausted.
15 #[error("lock busy after retry ({0})")]
16 LockBusyAfterRetry(&'static str),
17
18 /// The presented `CapToken`'s HMAC signature did not verify.
19 #[error("token signature invalid")]
20 BadSignature,
21
22 /// The presented `CapToken` is past its `expire_at`.
23 #[error("token expired")]
24 TokenExpired,
25
26 /// The presented `CapToken` has no uses left (`max_uses` budget spent).
27 #[error("token uses exhausted")]
28 TokenUsesExhausted,
29
30 /// No server-side record exists for the token. Carries the token
31 /// **fingerprint** (SHA-256 of the nonce, see `CapToken::fingerprint`)
32 /// — never the nonce itself, since this message can surface in HTTP
33 /// error bodies and logs (issue #14).
34 #[error("token not found in store (fp={0})")]
35 TokenNotFound(String),
36
37 /// The token's `Role` is not allow-listed for the requested `Verb` (see
38 /// `RoleVerbGate`).
39 #[error("role violation: role={role:?} verb={verb:?}")]
40 RoleViolation {
41 /// The role the token was minted for.
42 role: Role,
43 /// The verb that was rejected.
44 verb: Verb,
45 },
46
47 /// No task exists with the given id.
48 #[error("task not found: {0}")]
49 TaskNotFound(String),
50
51 /// No session is attached to the task.
52 #[error("session not found")]
53 SessionNotFound,
54
55 /// The resume key presented does not match any pending resume point.
56 #[error("resume key not found")]
57 ResumeKeyNotFound,
58
59 /// A generic named resource (other than task/session/token) was not
60 /// found.
61 #[error("resource not found: {0}")]
62 ResourceNotFound(String),
63
64 /// The requested state transition is not valid from the task's current
65 /// state.
66 #[error("invalid state transition: {0}")]
67 InvalidTransition(String),
68
69 /// Dispatching an attempt failed; the string carries the underlying
70 /// reason.
71 #[error("dispatch failed: {0}")]
72 DispatchFailed(String),
73
74 /// A poll operation exceeded its deadline without observing completion.
75 #[error("poll timeout")]
76 PollTimeout,
77
78 /// The task was cancelled.
79 #[error("cancelled")]
80 Cancelled,
81
82 /// A sub-task spawn would exceed the configured `max_spawn_depth`.
83 #[error("spawn depth exceeded: {current} >= max {max}")]
84 SpawnDepthExceeded {
85 /// The depth that would result from this spawn.
86 current: u32,
87 /// The configured maximum allowed depth.
88 max: u32,
89 },
90
91 /// The presented token is bound to a different task than the one
92 /// referenced by the call.
93 #[error("token task mismatch: token bound to {bound}, arg was {arg}")]
94 TokenTaskMismatch {
95 /// The task id the token is actually bound to.
96 bound: String,
97 /// The task id that was passed in the call.
98 arg: String,
99 },
100
101 /// Catch-all for invariant violations that don't have a dedicated
102 /// variant yet.
103 #[error("internal: {0}")]
104 Internal(String),
105
106 /// GH #31: writing a `SystemRefMode::File` body to
107 /// `SystemRefConfig.store_dir` failed (directory creation or file
108 /// write, both via `tokio::fs`).
109 #[error("system_ref store write failed: {0}")]
110 SystemRefWrite(#[from] std::io::Error),
111
112 /// GH #51 — completion-time verdict-contract enforcement: a
113 /// `channel: "body"` contract's completing value (or a `channel:
114 /// "part"` contract's staged `"verdict"` artifact value) is not a
115 /// member of the declared `values` set. Raised by the shared
116 /// completion-check embedded inside `Engine::submit_worker_result_trusted`
117 /// / `Engine::submit_output` — the single choke point every
118 /// completion route passes through.
119 #[error(
120 "verdict contract violation: {value:?} is not a member of the declared values {allowed:?}"
121 )]
122 VerdictValueRejected {
123 /// The value that failed membership.
124 value: String,
125 /// The contract's declared token set.
126 allowed: Vec<String>,
127 },
128
129 /// GH #51 — completion-time verdict-contract enforcement: a
130 /// `channel: "part"` contract's attempt completed without ever
131 /// staging a `"verdict"` artifact (presence, not just membership, is
132 /// checked at completion — the staging-time check only covers
133 /// membership for parts that WERE staged).
134 #[error("verdict contract violation: no staged \"verdict\" part found for this attempt; declared values {allowed:?}")]
135 VerdictPartMissing {
136 /// The contract's declared token set.
137 allowed: Vec<String>,
138 },
139}