Skip to main content

signal_fish_client/
error_codes.rs

1//! Error codes for structured error handling in the Signal Fish protocol.
2//!
3//! These codes are wire-compatible with the server's `ErrorCode` enum and
4//! serialize using `SCREAMING_SNAKE_CASE` to match the server's JSON format.
5
6use serde::{Deserialize, Serialize};
7use std::fmt;
8
9/// Structured error codes returned by the Signal Fish server.
10///
11/// Each variant corresponds to a specific error condition. The server sends these
12/// as `"SCREAMING_SNAKE_CASE"` strings (e.g., `"ROOM_NOT_FOUND"`).
13///
14/// Use [`description()`](ErrorCode::description) for a human-readable explanation.
15#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
16#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
17pub enum ErrorCode {
18    // Authentication errors
19    Unauthorized,
20    InvalidToken,
21    AuthenticationRequired,
22    InvalidAppId,
23    AppIdExpired,
24    AppIdRevoked,
25    AppIdSuspended,
26    MissingAppId,
27    AuthenticationTimeout,
28    SdkVersionUnsupported,
29    UnsupportedGameDataFormat,
30
31    // Validation errors
32    InvalidInput,
33    InvalidGameName,
34    InvalidRoomCode,
35    InvalidPlayerName,
36    InvalidMaxPlayers,
37    MessageTooLarge,
38
39    // Room errors
40    RoomNotFound,
41    RoomFull,
42    AlreadyInRoom,
43    NotInRoom,
44    RoomCreationFailed,
45    MaxRoomsPerGameExceeded,
46    InvalidRoomState,
47
48    // Authority errors
49    AuthorityNotSupported,
50    AuthorityConflict,
51    AuthorityDenied,
52
53    // Rate limiting
54    RateLimitExceeded,
55    TooManyConnections,
56
57    // Reconnection errors
58    ReconnectionFailed,
59    ReconnectionTokenInvalid,
60    ReconnectionExpired,
61    PlayerAlreadyConnected,
62
63    // Spectator errors
64    SpectatorNotAllowed,
65    TooManySpectators,
66    NotASpectator,
67    SpectatorJoinFailed,
68
69    // Server errors
70    InternalError,
71    StorageError,
72    ServiceUnavailable,
73}
74
75impl ErrorCode {
76    /// Returns a human-readable description of this error code.
77    ///
78    /// This method provides actionable error messages that SDK developers
79    /// can display to end users or use for debugging.
80    pub fn description(&self) -> &'static str {
81        match self {
82            // Authentication errors
83            Self::Unauthorized => {
84                "Access denied. Authentication credentials are missing or invalid."
85            }
86            Self::InvalidToken => {
87                "The authentication token is invalid, malformed, or has expired. Please obtain a new token."
88            }
89            Self::AuthenticationRequired => {
90                "This operation requires authentication. Please provide valid credentials."
91            }
92            Self::InvalidAppId => {
93                "The provided application ID is not recognized. Verify your app ID is correct."
94            }
95            Self::AppIdExpired => {
96                "The application ID has expired. Please renew your application registration."
97            }
98            Self::AppIdRevoked => {
99                "The application ID has been revoked. Contact the administrator for assistance."
100            }
101            Self::AppIdSuspended => {
102                "The application ID has been suspended. Contact the administrator for assistance."
103            }
104            Self::MissingAppId => {
105                "Application ID is required but was not provided. Include your app ID in the request."
106            }
107            Self::AuthenticationTimeout => {
108                "Authentication took too long to complete. Please try again."
109            }
110            Self::SdkVersionUnsupported => {
111                "The SDK version you are using is no longer supported. Please upgrade to the latest version."
112            }
113            Self::UnsupportedGameDataFormat => {
114                "The requested game data format is not supported by this server. Falling back to JSON encoding."
115            }
116
117            // Validation errors
118            Self::InvalidInput => {
119                "The provided input is invalid or malformed. Check your request parameters."
120            }
121            Self::InvalidGameName => {
122                "The game name is invalid. Game names must be non-empty and follow naming requirements."
123            }
124            Self::InvalidRoomCode => {
125                "The room code is invalid or malformed. Room codes must follow the required format."
126            }
127            Self::InvalidPlayerName => {
128                "The player name is invalid. Player names must be non-empty and meet length requirements."
129            }
130            Self::InvalidMaxPlayers => {
131                "The maximum player count is invalid. It must be a positive number within allowed limits."
132            }
133            Self::MessageTooLarge => {
134                "The message size exceeds the maximum allowed limit. Please send a smaller message."
135            }
136
137            // Room errors
138            Self::RoomNotFound => {
139                "The requested room could not be found. It may have been closed or the code is incorrect."
140            }
141            Self::RoomFull => {
142                "The room has reached its maximum player capacity. Try joining a different room."
143            }
144            Self::AlreadyInRoom => {
145                "You are already in a room. Leave the current room before joining another."
146            }
147            Self::NotInRoom => {
148                "You are not currently in any room. Join a room before performing this action."
149            }
150            Self::RoomCreationFailed => {
151                "Failed to create the room. Please try again or contact support if the issue persists."
152            }
153            Self::MaxRoomsPerGameExceeded => {
154                "The maximum number of rooms for this game has been reached. Please try again later."
155            }
156            Self::InvalidRoomState => {
157                "The room is in an invalid state for this operation. Try refreshing or rejoining the room."
158            }
159
160            // Authority errors
161            Self::AuthorityNotSupported => {
162                "Authority features are not enabled on this server. Check your server configuration."
163            }
164            Self::AuthorityConflict => {
165                "Another client has already claimed authority. Only one client can have authority at a time."
166            }
167            Self::AuthorityDenied => {
168                "You do not have permission to claim authority in this room."
169            }
170
171            // Rate limiting
172            Self::RateLimitExceeded => {
173                "Too many requests in a short time. Please slow down and try again later."
174            }
175            Self::TooManyConnections => {
176                "You have too many active connections. Close some connections before opening new ones."
177            }
178
179            // Reconnection errors
180            Self::ReconnectionFailed => {
181                "Failed to reconnect to the room. The session may have expired or the room may be closed."
182            }
183            Self::ReconnectionTokenInvalid => {
184                "The reconnection token is invalid or malformed. You may need to join the room again."
185            }
186            Self::ReconnectionExpired => {
187                "The reconnection window has expired. You must join the room again as a new player."
188            }
189            Self::PlayerAlreadyConnected => {
190                "This player is already connected to the room from another session."
191            }
192
193            // Spectator errors
194            Self::SpectatorNotAllowed => {
195                "Spectator mode is not enabled for this room. Only players can join."
196            }
197            Self::TooManySpectators => {
198                "The room has reached its maximum spectator capacity. Try again later."
199            }
200            Self::NotASpectator => {
201                "You are not a spectator in this room. This action is only available to spectators."
202            }
203            Self::SpectatorJoinFailed => {
204                "Failed to join as a spectator. The room may be full or spectating may be disabled."
205            }
206
207            // Server errors
208            Self::InternalError => {
209                "An internal server error occurred. Please try again or contact support if the issue persists."
210            }
211            Self::StorageError => {
212                "A storage error occurred while processing your request. Please try again later."
213            }
214            Self::ServiceUnavailable => {
215                "The service is temporarily unavailable. Please try again in a few moments."
216            }
217        }
218    }
219}
220
221impl fmt::Display for ErrorCode {
222    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
223        write!(f, "{}", self.description())
224    }
225}