scylla_cql/frame/
frame_errors.rs

1use std::error::Error;
2use std::sync::Arc;
3
4pub use super::request::{
5    auth_response::AuthResponseSerializationError,
6    batch::{BatchSerializationError, BatchStatementSerializationError},
7    execute::ExecuteSerializationError,
8    prepare::PrepareSerializationError,
9    query::{QueryParametersSerializationError, QuerySerializationError},
10    register::RegisterSerializationError,
11    startup::StartupSerializationError,
12};
13
14use super::response::CqlResponseKind;
15use super::TryFromPrimitiveError;
16use thiserror::Error;
17
18/// An error returned by `parse_response_body_extensions`.
19///
20/// It represents an error that occurred during deserialization of
21/// frame body extensions. These extensions include tracing id,
22/// warnings and custom payload.
23///
24/// Possible error kinds:
25/// - failed to decompress frame body (decompression is required for further deserialization)
26/// - failed to deserialize tracing id (body ext.)
27/// - failed to deserialize warnings list (body ext.)
28/// - failed to deserialize custom payload map (body ext.)
29#[derive(Error, Debug, Clone)]
30#[non_exhaustive]
31pub enum FrameBodyExtensionsParseError {
32    /// Frame is compressed, but no compression was negotiated for the connection.
33    #[error("Frame is compressed, but no compression negotiated for connection.")]
34    NoCompressionNegotiated,
35
36    /// Failed to deserialize frame trace id.
37    #[error("Malformed trace id: {0}")]
38    TraceIdParse(LowLevelDeserializationError),
39
40    /// Failed to deserialize warnings attached to frame.
41    #[error("Malformed warnings list: {0}")]
42    WarningsListParse(LowLevelDeserializationError),
43
44    /// Failed to deserialize frame's custom payload.
45    #[error("Malformed custom payload map: {0}")]
46    CustomPayloadMapParse(LowLevelDeserializationError),
47
48    /// Failed to decompress frame body (snap).
49    #[error("Snap decompression error: {0}")]
50    SnapDecompressError(Arc<dyn Error + Sync + Send>),
51
52    /// Failed to decompress frame body (lz4).
53    #[error("Error decompressing lz4 data {0}")]
54    Lz4DecompressError(Arc<dyn Error + Sync + Send>),
55}
56
57/// An error that occurred during frame header deserialization.
58#[derive(Debug, Error)]
59#[non_exhaustive]
60pub enum FrameHeaderParseError {
61    /// Failed to read the frame header from the socket.
62    #[error("Failed to read the frame header: {0}")]
63    HeaderIoError(std::io::Error),
64
65    /// Received a frame marked as coming from a client.
66    #[error("Received frame marked as coming from a client")]
67    FrameFromClient,
68
69    // FIXME: this should not belong here. User always expects a frame from server.
70    // This variant is only used in scylla-proxy - need to investigate it later.
71    #[error("Received frame marked as coming from the server")]
72    FrameFromServer,
73
74    /// Received a frame with unsupported version.
75    #[error("Received a frame from version {0}, but only 4 is supported")]
76    VersionNotSupported(u8),
77
78    /// Received unknown response opcode.
79    #[error("Unrecognized response opcode {0}")]
80    UnknownResponseOpcode(#[from] TryFromPrimitiveError<u8>),
81
82    /// Failed to read frame body from the socket.
83    #[error("Failed to read a chunk of response body. Expected {0} more bytes, error: {1}")]
84    BodyChunkIoError(usize, std::io::Error),
85
86    /// Connection was closed before whole frame was read.
87    #[error("Connection was closed before body was read: missing {0} out of {1}")]
88    ConnectionClosed(usize, usize),
89}
90
91/// An error that occurred during CQL request serialization.
92#[non_exhaustive]
93#[derive(Error, Debug, Clone)]
94pub enum CqlRequestSerializationError {
95    /// Failed to serialize STARTUP request.
96    #[error("Failed to serialize STARTUP request: {0}")]
97    StartupSerialization(#[from] StartupSerializationError),
98
99    /// Failed to serialize REGISTER request.
100    #[error("Failed to serialize REGISTER request: {0}")]
101    RegisterSerialization(#[from] RegisterSerializationError),
102
103    /// Failed to serialize AUTH_RESPONSE request.
104    #[error("Failed to serialize AUTH_RESPONSE request: {0}")]
105    AuthResponseSerialization(#[from] AuthResponseSerializationError),
106
107    /// Failed to serialize BATCH request.
108    #[error("Failed to serialize BATCH request: {0}")]
109    BatchSerialization(#[from] BatchSerializationError),
110
111    /// Failed to serialize PREPARE request.
112    #[error("Failed to serialize PREPARE request: {0}")]
113    PrepareSerialization(#[from] PrepareSerializationError),
114
115    /// Failed to serialize EXECUTE request.
116    #[error("Failed to serialize EXECUTE request: {0}")]
117    ExecuteSerialization(#[from] ExecuteSerializationError),
118
119    /// Failed to serialize QUERY request.
120    #[error("Failed to serialize QUERY request: {0}")]
121    QuerySerialization(#[from] QuerySerializationError),
122
123    /// Request body compression failed.
124    #[error("Snap compression error: {0}")]
125    SnapCompressError(Arc<dyn Error + Sync + Send>),
126}
127
128/// An error type returned when deserialization of CQL
129/// server response fails.
130#[non_exhaustive]
131#[derive(Error, Debug, Clone)]
132pub enum CqlResponseParseError {
133    #[error("Failed to deserialize ERROR response: {0}")]
134    CqlErrorParseError(#[from] CqlErrorParseError),
135    #[error("Failed to deserialize AUTH_CHALLENGE response: {0}")]
136    CqlAuthChallengeParseError(#[from] CqlAuthChallengeParseError),
137    #[error("Failed to deserialize AUTH_SUCCESS response: {0}")]
138    CqlAuthSuccessParseError(#[from] CqlAuthSuccessParseError),
139    #[error("Failed to deserialize AUTHENTICATE response: {0}")]
140    CqlAuthenticateParseError(#[from] CqlAuthenticateParseError),
141    #[error("Failed to deserialize SUPPORTED response: {0}")]
142    CqlSupportedParseError(#[from] CqlSupportedParseError),
143    #[error("Failed to deserialize EVENT response: {0}")]
144    CqlEventParseError(#[from] CqlEventParseError),
145    #[error(transparent)]
146    CqlResultParseError(#[from] CqlResultParseError),
147}
148
149impl CqlResponseParseError {
150    pub fn to_response_kind(&self) -> CqlResponseKind {
151        match self {
152            CqlResponseParseError::CqlErrorParseError(_) => CqlResponseKind::Error,
153            CqlResponseParseError::CqlAuthChallengeParseError(_) => CqlResponseKind::AuthChallenge,
154            CqlResponseParseError::CqlAuthSuccessParseError(_) => CqlResponseKind::AuthSuccess,
155            CqlResponseParseError::CqlAuthenticateParseError(_) => CqlResponseKind::Authenticate,
156            CqlResponseParseError::CqlSupportedParseError(_) => CqlResponseKind::Supported,
157            CqlResponseParseError::CqlEventParseError(_) => CqlResponseKind::Event,
158            CqlResponseParseError::CqlResultParseError(_) => CqlResponseKind::Result,
159        }
160    }
161}
162
163/// An error type returned when deserialization of ERROR response fails.
164#[non_exhaustive]
165#[derive(Error, Debug, Clone)]
166pub enum CqlErrorParseError {
167    #[error("Malformed error code: {0}")]
168    ErrorCodeParseError(LowLevelDeserializationError),
169    #[error("Malformed error reason: {0}")]
170    ReasonParseError(LowLevelDeserializationError),
171    #[error("Malformed error field {field} of DB error {db_error}: {err}")]
172    MalformedErrorField {
173        db_error: &'static str,
174        field: &'static str,
175        err: LowLevelDeserializationError,
176    },
177}
178
179/// An error type returned when deserialization of AUTH_CHALLENGE response fails.
180#[non_exhaustive]
181#[derive(Error, Debug, Clone)]
182pub enum CqlAuthChallengeParseError {
183    #[error("Malformed authenticate message: {0}")]
184    AuthMessageParseError(LowLevelDeserializationError),
185}
186
187/// An error type returned when deserialization of AUTH_SUCCESS response fails.
188#[non_exhaustive]
189#[derive(Error, Debug, Clone)]
190pub enum CqlAuthSuccessParseError {
191    #[error("Malformed success message: {0}")]
192    SuccessMessageParseError(LowLevelDeserializationError),
193}
194
195/// An error type returned when deserialization of AUTHENTICATE response fails.
196#[non_exhaustive]
197#[derive(Error, Debug, Clone)]
198pub enum CqlAuthenticateParseError {
199    #[error("Malformed authenticator name: {0}")]
200    AuthNameParseError(LowLevelDeserializationError),
201}
202
203/// An error type returned when deserialization of SUPPORTED response fails.
204#[non_exhaustive]
205#[derive(Error, Debug, Clone)]
206pub enum CqlSupportedParseError {
207    #[error("Malformed options map: {0}")]
208    OptionsMapDeserialization(LowLevelDeserializationError),
209}
210
211/// An error type returned when deserialization of RESULT response fails.
212#[non_exhaustive]
213#[derive(Error, Debug, Clone)]
214pub enum CqlResultParseError {
215    #[error("Malformed RESULT response id: {0}")]
216    ResultIdParseError(LowLevelDeserializationError),
217    #[error("Unknown RESULT response id: {0}")]
218    UnknownResultId(i32),
219    #[error("RESULT:Set_keyspace response deserialization failed: {0}")]
220    SetKeyspaceParseError(#[from] SetKeyspaceParseError),
221    // This is an error returned during deserialization of
222    // `RESULT::Schema_change` response, and not `EVENT` response.
223    #[error("RESULT:Schema_change response deserialization failed: {0}")]
224    SchemaChangeParseError(#[from] SchemaChangeEventParseError),
225    #[error("RESULT:Prepared response deserialization failed: {0}")]
226    PreparedParseError(#[from] PreparedParseError),
227    #[error("RESULT:Rows response deserialization failed: {0}")]
228    RawRowsParseError(#[from] RawRowsAndPagingStateResponseParseError),
229}
230
231#[non_exhaustive]
232#[derive(Error, Debug, Clone)]
233pub enum SetKeyspaceParseError {
234    #[error("Malformed keyspace name: {0}")]
235    MalformedKeyspaceName(#[from] LowLevelDeserializationError),
236}
237
238/// An error type returned when deserialization of
239/// `EVENT` response fails.
240#[non_exhaustive]
241#[derive(Error, Debug, Clone)]
242pub enum CqlEventParseError {
243    #[error("Malformed event type string: {0}")]
244    EventTypeParseError(LowLevelDeserializationError),
245    #[error("Unknown event type: {0}")]
246    UnknownEventType(String),
247    #[error("Failed to deserialize schema change event: {0}")]
248    SchemaChangeEventParseError(#[from] SchemaChangeEventParseError),
249    #[error("Failed to deserialize topology change event: {0}")]
250    TopologyChangeEventParseError(ClusterChangeEventParseError),
251    #[error("Failed to deserialize status change event: {0}")]
252    StatusChangeEventParseError(ClusterChangeEventParseError),
253}
254
255/// An error type returned when deserialization of
256/// SchemaChangeEvent fails.
257#[non_exhaustive]
258#[derive(Error, Debug, Clone)]
259pub enum SchemaChangeEventParseError {
260    #[error("Malformed schema change type string: {0}")]
261    TypeOfChangeParseError(LowLevelDeserializationError),
262    #[error("Malformed schema change target string:: {0}")]
263    TargetTypeParseError(LowLevelDeserializationError),
264    #[error("Malformed name of keyspace affected by schema change: {0}")]
265    AffectedKeyspaceParseError(LowLevelDeserializationError),
266    #[error("Malformed name of the table affected by schema change: {0}")]
267    AffectedTableNameParseError(LowLevelDeserializationError),
268    #[error("Malformed name of the target affected by schema change: {0}")]
269    AffectedTargetNameParseError(LowLevelDeserializationError),
270    #[error(
271        "Malformed number of arguments of the function/aggregate affected by schema change: {0}"
272    )]
273    ArgumentCountParseError(LowLevelDeserializationError),
274    #[error("Malformed argument of the function/aggregate affected by schema change: {0}")]
275    FunctionArgumentParseError(LowLevelDeserializationError),
276    #[error("Unknown target of schema change: {0}")]
277    UnknownTargetOfSchemaChange(String),
278}
279
280/// An error type returned when deserialization of [Status/Topology]ChangeEvent fails.
281#[non_exhaustive]
282#[derive(Error, Debug, Clone)]
283pub enum ClusterChangeEventParseError {
284    #[error("Malformed type of change: {0}")]
285    TypeOfChangeParseError(LowLevelDeserializationError),
286    #[error("Malformed node address: {0}")]
287    NodeAddressParseError(LowLevelDeserializationError),
288    #[error("Unknown type of change: {0}")]
289    UnknownTypeOfChange(String),
290}
291
292/// An error type returned when deserialization
293/// of `RESULT::`Prepared` response fails.
294#[non_exhaustive]
295#[derive(Debug, Error, Clone)]
296pub enum PreparedParseError {
297    #[error("Malformed prepared statement's id length: {0}")]
298    IdLengthParseError(LowLevelDeserializationError),
299    #[error("Invalid result metadata: {0}")]
300    ResultMetadataParseError(ResultMetadataParseError),
301    #[error("Invalid prepared metadata: {0}")]
302    PreparedMetadataParseError(PreparedMetadataParseError),
303    #[error("Non-zero paging state in result metadata: {0:?}")]
304    NonZeroPagingState(Arc<[u8]>),
305}
306
307/// An error that occurred during initial deserialization of
308/// `RESULT:Rows` response. Since the deserialization of rows is lazy,
309/// we initially only need to deserialize:
310/// - result metadata flags
311/// - column count (result metadata)
312/// - paging state response
313#[non_exhaustive]
314#[derive(Debug, Error, Clone)]
315pub enum RawRowsAndPagingStateResponseParseError {
316    /// Failed to parse metadata flags.
317    #[error("Malformed metadata flags: {0}")]
318    FlagsParseError(LowLevelDeserializationError),
319
320    /// Failed to parse column count.
321    #[error("Malformed column count: {0}")]
322    ColumnCountParseError(LowLevelDeserializationError),
323
324    /// Failed to parse paging state response.
325    #[error("Malformed paging state: {0}")]
326    PagingStateParseError(LowLevelDeserializationError),
327}
328
329/// An error type returned when deserialization
330/// of statement's prepared metadata failed.
331#[non_exhaustive]
332#[derive(Error, Debug, Clone)]
333pub enum PreparedMetadataParseError {
334    /// Failed to parse metadata flags.
335    #[error("Malformed metadata flags: {0}")]
336    FlagsParseError(LowLevelDeserializationError),
337
338    /// Failed to parse column count.
339    #[error("Malformed column count: {0}")]
340    ColumnCountParseError(LowLevelDeserializationError),
341
342    /// Failed to parse partition key count.
343    #[error("Malformed partition key count: {0}")]
344    PkCountParseError(LowLevelDeserializationError),
345
346    /// Failed to parse partition key index.
347    #[error("Malformed partition key index: {0}")]
348    PkIndexParseError(LowLevelDeserializationError),
349
350    /// Failed to parse global table spec.
351    #[error("Invalid global table spec: {0}")]
352    GlobalTableSpecParseError(#[from] TableSpecParseError),
353
354    /// Failed to parse column spec.
355    #[error("Invalid column spec: {0}")]
356    ColumnSpecParseError(#[from] ColumnSpecParseError),
357}
358
359/// An error returned when lazy deserialization of
360/// result metadata and rows count fails.
361#[non_exhaustive]
362#[derive(Error, Debug, Clone)]
363pub enum ResultMetadataAndRowsCountParseError {
364    /// Failed to deserialize result metadata.
365    #[error("Failed to lazily deserialize result metadata: {0}")]
366    ResultMetadataParseError(#[from] ResultMetadataParseError),
367
368    /// Received malformed rows count from the server.
369    #[error("Malformed rows count: {0}")]
370    RowsCountParseError(LowLevelDeserializationError),
371}
372
373/// An error type returned when deserialization
374/// of result metadata failed.
375#[non_exhaustive]
376#[derive(Error, Debug, Clone)]
377pub enum ResultMetadataParseError {
378    /// Failed to parse metadata flags.
379    #[error("Malformed metadata flags: {0}")]
380    FlagsParseError(LowLevelDeserializationError),
381
382    /// Failed to parse column count.
383    #[error("Malformed column count: {0}")]
384    ColumnCountParseError(LowLevelDeserializationError),
385
386    /// Failed to parse paging state response.
387    #[error("Malformed paging state: {0}")]
388    PagingStateParseError(LowLevelDeserializationError),
389
390    /// Failed to parse global table spec.
391    #[error("Invalid global table spec: {0}")]
392    GlobalTableSpecParseError(#[from] TableSpecParseError),
393
394    /// Failed to parse column spec.
395    #[error("Invalid column spec: {0}")]
396    ColumnSpecParseError(#[from] ColumnSpecParseError),
397}
398
399/// An error type returned when deserialization
400/// of table specification fails.
401#[non_exhaustive]
402#[derive(Error, Debug, Clone)]
403pub enum TableSpecParseError {
404    #[error("Malformed keyspace name: {0}")]
405    MalformedKeyspaceName(LowLevelDeserializationError),
406    #[error("Malformed table name: {0}")]
407    MalformedTableName(LowLevelDeserializationError),
408}
409
410/// An error type returned when deserialization
411/// of table column specifications fails.
412#[non_exhaustive]
413#[derive(Error, Debug, Clone)]
414#[error("Column spec deserialization failed, column index: {column_index}, error: {kind}")]
415pub struct ColumnSpecParseError {
416    pub column_index: usize,
417    pub kind: ColumnSpecParseErrorKind,
418}
419
420/// The type of error that appeared during deserialization
421/// of a column specification.
422#[non_exhaustive]
423#[derive(Error, Debug, Clone)]
424pub enum ColumnSpecParseErrorKind {
425    #[error("Invalid table spec: {0}")]
426    TableSpecParseError(#[from] TableSpecParseError),
427    #[error("Malformed column name: {0}")]
428    ColumnNameParseError(#[from] LowLevelDeserializationError),
429    #[error("Invalid column type: {0}")]
430    ColumnTypeParseError(#[from] CqlTypeParseError),
431}
432
433/// An error type returned when deserialization of CQL type name fails.
434#[non_exhaustive]
435#[derive(Error, Debug, Clone)]
436pub enum CqlTypeParseError {
437    #[error("Malformed type id: {0}")]
438    TypeIdParseError(LowLevelDeserializationError),
439    #[error("Malformed custom type name: {0}")]
440    CustomTypeNameParseError(LowLevelDeserializationError),
441    #[error("Unsupported custom type: {0}")]
442    CustomTypeUnsupported(String),
443    #[error("Malformed name of UDT keyspace: {0}")]
444    UdtKeyspaceNameParseError(LowLevelDeserializationError),
445    #[error("Malformed UDT name: {0}")]
446    UdtNameParseError(LowLevelDeserializationError),
447    #[error("Malformed UDT fields count: {0}")]
448    UdtFieldsCountParseError(LowLevelDeserializationError),
449    #[error("Malformed UDT's field name: {0}")]
450    UdtFieldNameParseError(LowLevelDeserializationError),
451    #[error("Malformed tuple length: {0}")]
452    TupleLengthParseError(LowLevelDeserializationError),
453    #[error("CQL Type not yet implemented, id: {0}")]
454    TypeNotImplemented(u16),
455}
456
457/// A low level deserialization error.
458///
459/// This type of error is returned when deserialization
460/// of some primitive value fails.
461///
462/// Possible error kinds:
463/// - generic io error - reading from buffer failed
464/// - out of range integer conversion
465/// - conversion errors - e.g. slice-to-array or primitive-to-enum
466/// - not enough bytes in the buffer to deserialize a value
467#[non_exhaustive]
468#[derive(Error, Debug, Clone)]
469pub enum LowLevelDeserializationError {
470    #[error(transparent)]
471    IoError(Arc<std::io::Error>),
472    #[error(transparent)]
473    TryFromIntError(#[from] std::num::TryFromIntError),
474    #[error(transparent)]
475    TryFromSliceError(#[from] std::array::TryFromSliceError),
476    #[error("Not enough bytes! expected: {expected}, received: {received}")]
477    TooFewBytesReceived { expected: usize, received: usize },
478    #[error("Invalid value length: {0}")]
479    InvalidValueLength(i32),
480    #[error("Unknown consistency: {0}")]
481    UnknownConsistency(#[from] TryFromPrimitiveError<u16>),
482    #[error("Invalid inet bytes length: {0}. Accepted lengths are 4 and 16 bytes.")]
483    InvalidInetLength(u8),
484    #[error("UTF8 deserialization failed: {0}")]
485    UTF8DeserializationError(#[from] std::str::Utf8Error),
486}
487
488impl From<std::io::Error> for LowLevelDeserializationError {
489    fn from(value: std::io::Error) -> Self {
490        Self::IoError(Arc::new(value))
491    }
492}