Errors and validation
Distinguish protocol, domain, guard, and lifecycle errors, and send bounded, safe error messages to clients.
Parsing a message, authorizing an identity, and satisfying a domain rule are separate checks. Use the typed outcome for the phase in which the error occurs.
Error boundaries#
| Boundary | Type / result |
|---|---|
| Before HTTP 101 | WsHandshakeRejection |
| Envelope, namespace, route | Protocol error or Close |
| Domain/action | WebSocketActionError |
| Guard | WebSocketGuardRejection: error, ACK, or Close |
| Connected/disconnected | WebSocketLifecycleError |
| Decode/encode | WebSocketCodecError |
| Fan-out | ConnectionError, partial receipt |
Do not return HTTP statuses after 101. A lifecycle error is not a message ACK. Handshake and client targets have their own error contracts.
Parsing and business rules#
Payload<T> parses a DTO with Serde. An empty name, an invalid date range, or a user's access to an object is checked separately. Do not add annotations as though a general DTO validation derive existed; establish the rule in a service, custom extractor, or action boundary.
if input.text.trim().is_empty() {
return Err(WebSocketActionError::rejected(
WebSocketErrorCode::new("TEXT_REQUIRED").expect("sabit kod"),
"Metin boş olamaz.",
).expect("sabit mesaj"));
}A complete example includes the DTO and imports for this snippet. The AuthorizedSubject extractor checks that identity exists; it does not verify credentials.
Public text and internal errors#
Error codes must be static and at most 64 bytes. The first character is an uppercase ASCII letter; the rest are uppercase letters, digits, or underscores. A public message must be nonempty, contain no control characters, and be at most 1024 bytes. A Close reason is at most 123 bytes; the Close code must also be valid.
WebSocketActionError::internal(source) preserves the original error through source() without repeating its sensitive contents in Debug/Display or wire text. Choose appropriate fields for application logs as well. The example's expect is suitable for fixed codes/text you control; do not use unchecked expect on user-supplied text.
Rejection and retries#
A guard's ack(code, public_message) returns a safe {code, message}; it does not accept arbitrary DTOs or retry metadata. Missing ACK authority does not cause a new ID to be generated. Choosing Close ends the connection; an error may be sufficient when rejecting only the message.
Serialization and transport failures can happen after action success. Do not assume all side effects were rolled back because an error was returned. Handle transactions, partial broadcasts, and deadlines separately.
Sources for this page v0.1.0
This guide is based on the reviewed framework commit.