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}