Skip to main content
The ScyllaDB Rust Driver uses a comprehensive set of error types to provide detailed information about failures at different levels of operation. Understanding these error types helps you handle failures appropriately and build robust applications.

Error Categories

Errors in the driver are organized into several categories:
  • Execution Errors - High-level errors from query execution
  • Request Errors - Errors from individual request attempts
  • Connection Errors - Low-level connection issues
  • Metadata Errors - Cluster metadata fetch failures
  • Session Creation Errors - Errors during session initialization

Main Error Types

ExecutionError

The main error type returned from query execution methods like query_unpaged(), execute_unpaged(), and batch().
pub enum ExecutionError {
    BadQuery(BadQuery),
    EmptyPlan,
    PrepareError(PrepareError),
    ConnectionPoolError(ConnectionPoolError),
    LastAttemptError(RequestAttemptError),
    RequestTimeout(Duration),
    UseKeyspaceError(UseKeyspaceError),
    SchemaAgreementError(SchemaAgreementError),
    MetadataError(MetadataError),
}
Variants:
  • BadQuery - Invalid statement passed by caller (serialization errors, invalid partition keys, etc.)
  • EmptyPlan - Load balancing policy returned an empty execution plan
  • PrepareError - Failed to prepare an unprepared statement with parameters
  • ConnectionPoolError - Selected node’s connection pool is in an invalid state
  • LastAttemptError - Error from the last attempt to execute the request
  • RequestTimeout - Request exceeded the client-side timeout
  • UseKeyspaceError - USE KEYSPACE <> request failed
  • SchemaAgreementError - Failed to await schema agreement
  • MetadataError - Metadata error during schema agreement
Example:
use scylla::errors::ExecutionError;

match session.query_unpaged("SELECT * FROM ks.tab", &[]).await {
    Ok(result) => { /* process result */ }
    Err(ExecutionError::RequestTimeout(timeout)) => {
        eprintln!("Query timed out after {:?}", timeout);
    }
    Err(ExecutionError::LastAttemptError(e)) => {
        eprintln!("Request failed: {}", e);
    }
    Err(e) => {
        eprintln!("Execution error: {}", e);
    }
}

RequestAttemptError

Error from a single attempt to execute a query. The retry policy uses this error to decide whether to retry.
pub enum RequestAttemptError {
    SerializationError(SerializationError),
    CqlRequestSerialization(CqlRequestSerializationError),
    UnableToAllocStreamId,
    BrokenConnectionError(BrokenConnectionError),
    BodyExtensionsParseError(FrameBodyExtensionsParseError),
    CqlResultParseError(CqlResultParseError),
    CqlErrorParseError(CqlErrorParseError),
    DbError(DbError, String),
    UnexpectedResponse(CqlResponseKind),
    RepreparedIdChanged { statement: String, expected_id: Vec<u8>, reprepared_id: Vec<u8> },
    RepreparedIdMissingInBatch,
    NonfinishedPagingState,
}
Variants:
  • SerializationError - Failed to serialize query parameters
  • CqlRequestSerialization - Failed to serialize the CQL request
  • UnableToAllocStreamId - No available stream ID for the request
  • BrokenConnectionError - Connection broke during execution
  • BodyExtensionsParseError - Failed to deserialize frame body extensions
  • CqlResultParseError - Failed to deserialize RESULT response
  • CqlErrorParseError - Failed to deserialize ERROR response
  • DbError(DbError, String) - Database returned an error (see DbError)
  • UnexpectedResponse - Received unexpected response from server
  • RepreparedIdChanged - Prepared statement ID changed after repreparation
  • RepreparedIdMissingInBatch - Reprepared statement ID not in batch
  • NonfinishedPagingState - Unpaged query returned non-empty paging state
Example:
use scylla::errors::{ExecutionError, RequestAttemptError, DbError};

match session.execute_unpaged(&prepared, values).await {
    Err(ExecutionError::LastAttemptError(
        RequestAttemptError::DbError(db_err, msg)
    )) => {
        match db_err {
            DbError::Unavailable { consistency, required, alive } => {
                eprintln!("Not enough replicas: need {}, have {}", required, alive);
            }
            DbError::WriteTimeout { .. } => {
                eprintln!("Write timed out: {}", msg);
            }
            _ => eprintln!("Database error: {} - {}", db_err, msg),
        }
    }
    Err(e) => eprintln!("Error: {}", e),
    Ok(result) => { /* success */ }
}

DbError

Database errors returned by ScyllaDB/Cassandra in response to queries. Re-exported from scylla_cql::frame::response::error.
pub enum DbError {
    ServerError,
    ProtocolError,
    AuthenticationError,
    Unavailable { consistency: Consistency, required: i32, alive: i32 },
    Overloaded,
    IsBootstrapping,
    TruncateError,
    WriteTimeout { consistency: Consistency, received: i32, required: i32, write_type: WriteType },
    ReadTimeout { consistency: Consistency, received: i32, required: i32, data_present: bool },
    ReadFailure { consistency: Consistency, received: i32, required: i32, numfailures: i32, data_present: bool },
    FunctionFailure { keyspace: String, function: String, arg_types: Vec<String> },
    WriteFailure { consistency: Consistency, received: i32, required: i32, numfailures: i32, write_type: WriteType },
    SyntaxError,
    Unauthorized,
    Invalid,
    ConfigError,
    AlreadyExists { keyspace: String, table: String },
    Unprepared { statement_id: Bytes },
    RateLimitReached { op_type: OperationType, rejected_by_coordinator: bool },
    Other(i32),
}
Common Variants:
  • Unavailable - Not enough replicas available for the consistency level
  • WriteTimeout - Write acknowledgment timed out
  • ReadTimeout - Read response timed out
  • Overloaded - Coordinator node is overloaded
  • SyntaxError - Invalid CQL syntax
  • AlreadyExists - Table/keyspace already exists
  • Unprepared - Prepared statement is unknown to the server
  • Invalid - Query is invalid (e.g., wrong column type)
Example:
use scylla::errors::{DbError, ExecutionError, RequestAttemptError};

if let Err(ExecutionError::LastAttemptError(
    RequestAttemptError::DbError(DbError::AlreadyExists { keyspace, table }, _)
)) = session.query_unpaged("CREATE TABLE ks.tab (a int PRIMARY KEY)", &[]).await {
    println!("Table {}.{} already exists", keyspace, table);
}

PrepareError

Error returned from Session::prepare().
pub enum PrepareError {
    ConnectionPoolError(ConnectionPoolError),
    AllAttemptsFailed { first_attempt: RequestAttemptError },
    PreparedStatementIdsMismatch,
}
Variants:
  • ConnectionPoolError - Failed to find a node with working connection pool
  • AllAttemptsFailed - Preparation failed on every connection
  • PreparedStatementIdsMismatch - Different connections returned different prepared statement IDs
Example:
use scylla::errors::PrepareError;

match session.prepare("SELECT * FROM ks.tab WHERE a = ?").await {
    Ok(prepared) => { /* use prepared */ }
    Err(PrepareError::AllAttemptsFailed { first_attempt }) => {
        eprintln!("Prepare failed: {}", first_attempt);
    }
    Err(e) => eprintln!("Prepare error: {}", e),
}

NewSessionError

Error from session creation (via SessionBuilder::build() or Session::connect()).
pub enum NewSessionError {
    FailedToResolveAnyHostname(Vec<String>),
    EmptyKnownNodesList,
    MetadataError(MetadataError),
    UseKeyspaceError(UseKeyspaceError),
}
Variants:
  • FailedToResolveAnyHostname - Couldn’t resolve any provided hostname
  • EmptyKnownNodesList - No known nodes provided
  • MetadataError - Failed to perform initial metadata fetch
  • UseKeyspaceError - Failed to execute USE KEYSPACE during initialization
Example:
use scylla::errors::NewSessionError;
use scylla::client::session_builder::SessionBuilder;

match SessionBuilder::new()
    .known_node("invalid-hostname:9042")
    .build()
    .await
{
    Ok(session) => { /* use session */ }
    Err(NewSessionError::FailedToResolveAnyHostname(hosts)) => {
        eprintln!("Failed to resolve: {:?}", hosts);
    }
    Err(e) => eprintln!("Session creation failed: {}", e),
}

ConnectionError

Connection-level errors indicating the connection can no longer be used.
pub enum ConnectionError {
    ConnectTimeout,
    IoError(Arc<std::io::Error>),
    NoSourcePortForShard(u32),
    TranslationError(TranslationError),
    BrokenConnection(BrokenConnectionError),
    ConnectionSetupRequestError(ConnectionSetupRequestError),
}
Variants:
  • ConnectTimeout - Connect timeout elapsed
  • IoError - I/O error occurred
  • NoSourcePortForShard - Couldn’t find free source port for shard
  • TranslationError - Address translation failed
  • BrokenConnection - Connection broke after being established
  • ConnectionSetupRequestError - Connection setup request failed

MetadataError

Errors during cluster metadata fetch and verification.
pub enum MetadataError {
    ConnectionPoolError(ConnectionPoolError),
    FetchError(MetadataFetchError),
    Peers(PeersMetadataError),
    Keyspaces(KeyspacesMetadataError),
    Udts(UdtMetadataError),
    Tables(TablesMetadataError),
}
Variants:
  • ConnectionPoolError - Control connection pool error
  • FetchError - Failed to fetch metadata from system tables
  • Peers - Bad peers metadata
  • Keyspaces - Bad keyspaces metadata
  • Udts - Bad UDT metadata
  • Tables - Bad tables metadata

SchemaAgreementError

Error when waiting for schema agreement across cluster nodes.
pub enum SchemaAgreementError {
    ConnectionPoolError(ConnectionPoolError),
    PrepareError(PrepareError),
    RequestError(RequestAttemptError),
    TracesEventsIntoRowsResultError(IntoRowsResultError),
    SingleRowError(SingleRowError),
    Timeout(Duration),
    RequiredHostAbsent(Uuid),
}
Example:
use scylla::errors::SchemaAgreementError;

match session.await_schema_agreement().await {
    Ok(version) => println!("Schema agreement: {}", version),
    Err(SchemaAgreementError::Timeout(dur)) => {
        eprintln!("Schema agreement timed out after {:?}", dur);
    }
    Err(e) => eprintln!("Schema agreement error: {}", e),
}

BadQuery

Errors caused by invalid statements passed by the caller.
pub enum BadQuery {
    PartitionKeyExtraction,
    SerializationError(SerializationError),
    ValuesTooLongForKey(usize, usize),
    TooManyQueriesInBatchStatement(usize),
}
Variants:
  • PartitionKeyExtraction - Unable to extract partition key from prepared statement
  • SerializationError - Failed to serialize values
  • ValuesTooLongForKey - Serialized values too long for partition key computation
  • TooManyQueriesInBatchStatement - Batch exceeds 65,535 statements

Query Result Errors

Errors related to query result processing. See QueryResult and QueryRowsResult for details.

IntoRowsResultError

From QueryResult::into_rows_result():
pub enum IntoRowsResultError {
    ResultNotRows(QueryResult),
    ResultMetadataLazyDeserializationError(ResultMetadataAndRowsCountParseError),
}

FirstRowError

From QueryRowsResult::first_row():
pub enum FirstRowError {
    RowsEmpty,
    TypeCheckFailed(TypeCheckError),
    DeserializationFailed(DeserializationError),
}

SingleRowError

From QueryRowsResult::single_row():
pub enum SingleRowError {
    UnexpectedRowCount(usize),
    TypeCheckFailed(TypeCheckError),
    DeserializationFailed(DeserializationError),
}

Error Handling Patterns

Retryable vs Non-Retryable

Some errors are retryable, others are not:
use scylla::errors::{DbError, ExecutionError, RequestAttemptError};

match session.execute_unpaged(&prepared, values).await {
    Err(ExecutionError::LastAttemptError(
        RequestAttemptError::DbError(db_err, _)
    )) => {
        match db_err {
            // Retryable - temporary unavailability
            DbError::Unavailable { .. } | 
            DbError::Overloaded | 
            DbError::IsBootstrapping => {
                // Retry logic or wait
            }
            // Not retryable - permanent errors
            DbError::SyntaxError | 
            DbError::Invalid | 
            DbError::AlreadyExists { .. } => {
                // Fix query or handle appropriately
            }
            _ => {}
        }
    }
    _ => {}
}

Extracting Database Errors

use scylla::errors::{ExecutionError, RequestAttemptError, DbError};

fn extract_db_error(err: &ExecutionError) -> Option<&DbError> {
    match err {
        ExecutionError::LastAttemptError(
            RequestAttemptError::DbError(db_err, _)
        ) => Some(db_err),
        _ => None,
    }
}

if let Some(DbError::Unavailable { required, alive, .. }) = extract_db_error(&error) {
    eprintln!("Need {} replicas, only {} alive", required, alive);
}

Handling Timeouts

use scylla::errors::ExecutionError;
use std::time::Duration;

match session.query_unpaged(query, values).await {
    Err(ExecutionError::RequestTimeout(timeout)) => {
        eprintln!("Query timed out after {:?}", timeout);
        // Consider increasing timeout or investigating performance
    }
    Err(ExecutionError::LastAttemptError(
        RequestAttemptError::DbError(DbError::WriteTimeout { .. }, _)
    )) => {
        eprintln!("Server-side write timeout");
        // Data may or may not be written
    }
    _ => {}
}

Connection Issues

use scylla::errors::{ConnectionPoolError, ExecutionError};

match session.query_unpaged(query, values).await {
    Err(ExecutionError::ConnectionPoolError(
        ConnectionPoolError::Broken { last_connection_error }
    )) => {
        eprintln!("Connection pool broken: {}", last_connection_error);
        // May need to wait for connection recovery
    }
    Err(ExecutionError::EmptyPlan) => {
        eprintln!("No nodes available in execution plan");
        // Check load balancing policy configuration
    }
    _ => {}
}

Re-exported Error Types

The following error types are re-exported from scylla_cql:
  • DeserializationError - Row/value deserialization errors
  • TypeCheckError - Type checking errors
  • SerializationError - Value serialization errors
  • CqlRequestSerializationError - CQL request frame serialization errors
  • CqlResponseParseError - CQL response frame parsing errors

Build docs developers (and LLMs) love