arbiter_session/error.rs
1use thiserror::Error;
2use uuid::Uuid;
3
4/// Errors from session operations.
5///
6/// Display impls are intentionally opaque — they appear in
7/// HTTP error responses sent to agents. Internal fields are preserved for
8/// structured logging via Debug. Previously, Display exposed budget limits,
9/// rate limit values, tool names, and session caps to untrusted agents.
10#[derive(Debug, Error)]
11pub enum SessionError {
12 /// The referenced session does not exist.
13 #[error("session not found")]
14 NotFound(Uuid),
15
16 /// The session has expired (time limit exceeded).
17 #[error("session expired")]
18 Expired(Uuid),
19
20 /// The session's call budget has been exhausted.
21 #[error("session budget exceeded")]
22 BudgetExceeded {
23 session_id: Uuid,
24 limit: u64,
25 used: u64,
26 },
27
28 /// The requested tool is not in the session's authorized set.
29 #[error("tool not authorized in session")]
30 ToolNotAuthorized { session_id: Uuid, tool: String },
31
32 /// The session has already been closed.
33 #[error("session already closed")]
34 AlreadyClosed(Uuid),
35
36 /// The session's per-minute rate limit has been exceeded.
37 #[error("session rate limit exceeded")]
38 RateLimited {
39 session_id: Uuid,
40 limit_per_minute: u64,
41 },
42
43 /// The presenting agent does not match the session's bound agent.
44 #[error("agent mismatch")]
45 AgentMismatch {
46 session_id: Uuid,
47 expected: Uuid,
48 actual: Uuid,
49 },
50
51 /// Storage write-through failed after updating cache.
52 /// The session state in the cache is ahead of durable storage.
53 #[error("storage write-through failed")]
54 StorageWriteThrough { session_id: Uuid, detail: String },
55
56 /// The agent has reached the maximum number of concurrent active sessions.
57 ///
58 /// P0: Per-agent session cap to prevent session multiplication attacks.
59 #[error("too many concurrent sessions")]
60 TooManySessions {
61 agent_id: String,
62 max: u64,
63 current: u64,
64 },
65}