Skip to main content

pylon_kernel/
errors.rs

1//! Centralized error code constants.
2//!
3//! Using string constants (instead of an enum) preserves the existing
4//! `{code: String, message: String}` wire shape while giving Rust callers
5//! and clients a single source of truth for the vocabulary.
6//!
7//! The TypeScript codegen emits these as a typed union so clients can
8//! exhaustively match on error codes.
9
10// ---------------------------------------------------------------------------
11// Auth
12// ---------------------------------------------------------------------------
13
14pub const AUTH_REQUIRED: &str = "AUTH_REQUIRED";
15pub const AUTH_UPGRADE_FAILED: &str = "UPGRADE_FAILED";
16pub const INVALID_CODE: &str = "INVALID_CODE";
17pub const OAUTH_INVALID_STATE: &str = "OAUTH_INVALID_STATE";
18pub const OAUTH_TOKEN_EXCHANGE_FAILED: &str = "OAUTH_TOKEN_EXCHANGE_FAILED";
19pub const PROVIDER_NOT_FOUND: &str = "PROVIDER_NOT_FOUND";
20pub const SESSION_EXPIRED: &str = "SESSION_EXPIRED";
21pub const SESSION_NOT_FOUND: &str = "SESSION_NOT_FOUND";
22pub const FORBIDDEN: &str = "FORBIDDEN";
23pub const POLICY_DENIED: &str = "POLICY_DENIED";
24pub const UNAUTHORIZED: &str = "UNAUTHORIZED";
25
26// ---------------------------------------------------------------------------
27// Request validation
28// ---------------------------------------------------------------------------
29
30pub const INVALID_JSON: &str = "INVALID_JSON";
31pub const INVALID_ARGS: &str = "INVALID_ARGS";
32pub const INVALID_COLUMN: &str = "INVALID_COLUMN";
33pub const INVALID_QUERY: &str = "INVALID_QUERY";
34pub const INVALID_DATA: &str = "INVALID_DATA";
35pub const INVALID_FILE_ID: &str = "INVALID_FILE_ID";
36pub const MISSING_EMAIL: &str = "MISSING_EMAIL";
37pub const MISSING_USER_ID: &str = "MISSING_USER_ID";
38pub const MISSING_CODE: &str = "MISSING_CODE";
39pub const MISSING_FIELD: &str = "MISSING_FIELD";
40pub const MISSING_ROOM: &str = "MISSING_ROOM";
41pub const MISSING_TOPIC: &str = "MISSING_TOPIC";
42pub const MISSING_NAME: &str = "MISSING_NAME";
43pub const MISSING_OPERATIONS: &str = "MISSING_OPERATIONS";
44pub const PAYLOAD_TOO_LARGE: &str = "PAYLOAD_TOO_LARGE";
45
46// ---------------------------------------------------------------------------
47// Data / lookup
48// ---------------------------------------------------------------------------
49
50pub const NOT_FOUND: &str = "NOT_FOUND";
51pub const ENTITY_NOT_FOUND: &str = "ENTITY_NOT_FOUND";
52pub const ACTION_NOT_FOUND: &str = "ACTION_NOT_FOUND";
53pub const FN_NOT_FOUND: &str = "FN_NOT_FOUND";
54pub const FILE_NOT_FOUND: &str = "FILE_NOT_FOUND";
55pub const SHARD_NOT_FOUND: &str = "SHARD_NOT_FOUND";
56pub const RELATION_NOT_FOUND: &str = "RELATION_NOT_FOUND";
57
58// ---------------------------------------------------------------------------
59// Database / internal
60// ---------------------------------------------------------------------------
61
62pub const QUERY_FAILED: &str = "QUERY_FAILED";
63pub const INSERT_FAILED: &str = "INSERT_FAILED";
64pub const UPDATE_FAILED: &str = "UPDATE_FAILED";
65pub const DELETE_FAILED: &str = "DELETE_FAILED";
66pub const SCHEMA_INIT_FAILED: &str = "SCHEMA_INIT_FAILED";
67pub const LOCK_FAILED: &str = "LOCK_FAILED";
68pub const NESTED_TRANSACTION: &str = "NESTED_TRANSACTION";
69pub const EXPORT_FAILED: &str = "EXPORT_FAILED";
70pub const NOT_SUPPORTED: &str = "NOT_SUPPORTED";
71pub const NOT_IMPLEMENTED: &str = "NOT_IMPLEMENTED";
72pub const NOT_AVAILABLE: &str = "NOT_AVAILABLE";
73
74// ---------------------------------------------------------------------------
75// Transport / platform
76// ---------------------------------------------------------------------------
77
78pub const RATE_LIMITED: &str = "RATE_LIMITED";
79pub const METHOD_NOT_ALLOWED: &str = "METHOD_NOT_ALLOWED";
80pub const PROTOCOL_ERROR: &str = "PROTOCOL_ERROR";
81pub const RUNNER_EXITED: &str = "RUNNER_EXITED";
82pub const RUNNER_NOT_STARTED: &str = "RUNNER_NOT_STARTED";
83pub const IO_ERROR: &str = "IO_ERROR";
84pub const AI_NOT_CONFIGURED: &str = "AI_NOT_CONFIGURED";
85pub const AI_REQUEST_FAILED: &str = "AI_REQUEST_FAILED";
86pub const EMAIL_SEND_FAILED: &str = "EMAIL_SEND_FAILED";
87
88// ---------------------------------------------------------------------------
89// Workflows / jobs / shards
90// ---------------------------------------------------------------------------
91
92pub const WORKFLOW_START_FAILED: &str = "WORKFLOW_START_FAILED";
93pub const WORKFLOW_ADVANCE_FAILED: &str = "WORKFLOW_ADVANCE_FAILED";
94pub const WORKFLOW_EVENT_FAILED: &str = "WORKFLOW_EVENT_FAILED";
95pub const WORKFLOW_CANCEL_FAILED: &str = "WORKFLOW_CANCEL_FAILED";
96pub const INPUT_REJECTED: &str = "INPUT_REJECTED";
97pub const SUBSCRIBE_FAILED: &str = "SUBSCRIBE_FAILED";
98pub const SHARDS_NOT_AVAILABLE: &str = "SHARDS_NOT_AVAILABLE";
99
100/// All error codes, ordered for codegen.
101pub const ALL_CODES: &[&str] = &[
102    AUTH_REQUIRED,
103    AUTH_UPGRADE_FAILED,
104    INVALID_CODE,
105    OAUTH_INVALID_STATE,
106    OAUTH_TOKEN_EXCHANGE_FAILED,
107    PROVIDER_NOT_FOUND,
108    SESSION_EXPIRED,
109    SESSION_NOT_FOUND,
110    FORBIDDEN,
111    POLICY_DENIED,
112    UNAUTHORIZED,
113    INVALID_JSON,
114    INVALID_ARGS,
115    INVALID_COLUMN,
116    INVALID_QUERY,
117    INVALID_DATA,
118    INVALID_FILE_ID,
119    MISSING_EMAIL,
120    MISSING_USER_ID,
121    MISSING_CODE,
122    MISSING_FIELD,
123    MISSING_ROOM,
124    MISSING_TOPIC,
125    MISSING_NAME,
126    MISSING_OPERATIONS,
127    PAYLOAD_TOO_LARGE,
128    NOT_FOUND,
129    ENTITY_NOT_FOUND,
130    ACTION_NOT_FOUND,
131    FN_NOT_FOUND,
132    FILE_NOT_FOUND,
133    SHARD_NOT_FOUND,
134    RELATION_NOT_FOUND,
135    QUERY_FAILED,
136    INSERT_FAILED,
137    UPDATE_FAILED,
138    DELETE_FAILED,
139    SCHEMA_INIT_FAILED,
140    LOCK_FAILED,
141    NESTED_TRANSACTION,
142    EXPORT_FAILED,
143    NOT_SUPPORTED,
144    NOT_IMPLEMENTED,
145    NOT_AVAILABLE,
146    RATE_LIMITED,
147    METHOD_NOT_ALLOWED,
148    PROTOCOL_ERROR,
149    RUNNER_EXITED,
150    RUNNER_NOT_STARTED,
151    IO_ERROR,
152    AI_NOT_CONFIGURED,
153    AI_REQUEST_FAILED,
154    EMAIL_SEND_FAILED,
155    WORKFLOW_START_FAILED,
156    WORKFLOW_ADVANCE_FAILED,
157    WORKFLOW_EVENT_FAILED,
158    WORKFLOW_CANCEL_FAILED,
159    INPUT_REJECTED,
160    SUBSCRIBE_FAILED,
161    SHARDS_NOT_AVAILABLE,
162];
163
164#[cfg(test)]
165mod tests {
166    use super::*;
167
168    #[test]
169    fn all_codes_nonempty() {
170        assert!(!ALL_CODES.is_empty());
171    }
172
173    #[test]
174    fn all_codes_unique() {
175        let mut seen = std::collections::HashSet::new();
176        for code in ALL_CODES {
177            assert!(seen.insert(*code), "duplicate code: {code}");
178        }
179    }
180
181    #[test]
182    fn all_codes_uppercase_snake() {
183        for code in ALL_CODES {
184            assert!(
185                code.chars()
186                    .all(|c| c.is_ascii_uppercase() || c == '_' || c.is_ascii_digit()),
187                "code not UPPER_SNAKE_CASE: {code}"
188            );
189        }
190    }
191}