Skip to main content
Drift SDK defines comprehensive error types for handling both SDK-level and on-chain program errors.

SdkError

The main error type returned by SDK functions.
pub enum SdkError {
    Rpc(Box<solana_rpc_client_api::client_error::Error>),
    Ws(Box<drift_pubsub_client::PubsubClientError>),
    Anchor(Box<anchor_lang::error::Error>),
    Deserializing,
    InvalidAccount,
    InvalidOracle,
    InvalidSeed,
    InvalidBase58,
    NoPosition(u16),
    OutOfSOL,
    Signing(Box<solana_sdk::signer::SignerError>),
    WebsocketError,
    MissedHeartbeat,
    UnsupportedAccountData,
    CouldntDecode(base64::DecodeError),
    CouldntJoin(tokio::task::JoinError),
    CouldntUnsubscribe,
    MathError(&'static str),
    BorrowMutError(BorrowMutError),
    BorrowError(BorrowError),
    Generic(String),
    MaxReconnectionAttemptsReached,
    JitOrderNotFound,
    NoMarketData(MarketId),
    NoAccountData(Pubkey),
    AlreadySubscribed,
    InvalidUrl,
    WsClient(Box<tungstenite::Error>),
    LibDriftVersion,
    WalletSigningDisabled,
    Grpc(Box<GrpcError>),
}

Result Type

pub type SdkResult<T> = Result<T, SdkError>;
Most SDK functions return SdkResult<T> which is an alias for Result<T, SdkError>.

Common Error Variants

Network Errors

Rpc

RPC client errors from Solana.
SdkError::Rpc(Box<solana_rpc_client_api::client_error::Error>)
Common causes:
  • Network connectivity issues
  • RPC endpoint errors
  • Transaction simulation failures

Ws

WebSocket connection errors.
SdkError::Ws(Box<drift_pubsub_client::PubsubClientError>)

Grpc

gRPC connection errors.
SdkError::Grpc(Box<GrpcError>)

Data Errors

InvalidAccount

The account data is not a valid Drift account.
SdkError::InvalidAccount

InvalidOracle

The oracle account is invalid or not supported.
SdkError::InvalidOracle

Deserializing

Failed to deserialize account data.
SdkError::Deserializing

NoPosition

User does not have a position in the specified market.
SdkError::NoPosition(u16)  // market_index
Example:
match result {
    Err(SdkError::NoPosition(market_index)) => {
        println!("No position in market {}", market_index);
    }
    Ok(position) => {
        // Use position
    }
    Err(e) => return Err(e),
}

NoMarketData

Market data not available - need to subscribe to the market.
SdkError::NoMarketData(MarketId)
Example:
match result {
    Err(SdkError::NoMarketData(market_id)) => {
        println!("Please subscribe to market {:?}", market_id);
    }
    Ok(data) => {
        // Use data
    }
    Err(e) => return Err(e),
}

NoAccountData

Account data not available.
SdkError::NoAccountData(Pubkey)

Transaction Errors

OutOfSOL

Insufficient SOL balance for transaction fees or rent.
SdkError::OutOfSOL

Signing

Error signing transaction.
SdkError::Signing(Box<solana_sdk::signer::SignerError>)

WalletSigningDisabled

Attempted to sign with a read-only wallet.
SdkError::WalletSigningDisabled

Math Errors

MathError

Mathematical operation error (overflow, underflow, division by zero).
SdkError::MathError(&'static str)  // description

Subscription Errors

AlreadySubscribed

Attempted to subscribe when already subscribed.
SdkError::AlreadySubscribed

CouldntUnsubscribe

Failed to unsubscribe from updates.
SdkError::CouldntUnsubscribe

MissedHeartbeat

DLOB heartbeat was missed.
SdkError::MissedHeartbeat

Connection Errors

MaxReconnectionAttemptsReached

Exhausted reconnection attempts.
SdkError::MaxReconnectionAttemptsReached

WebsocketError

Generic WebSocket error.
SdkError::WebsocketError

Other Errors

Generic

Generic error with custom message.
SdkError::Generic(String)

InvalidSeed

Invalid keypair seed provided.
SdkError::InvalidSeed

JitOrderNotFound

JIT taker order not found.
SdkError::JitOrderNotFound

Error Handling Methods

to_anchor_error_code

Extract Drift program error code from RPC error.
pub fn to_anchor_error_code(&self) -> Option<ProgramError>
Returns: Some(ProgramError) if the error contains a Drift program error Example:
if let Some(program_error) = sdk_error.to_anchor_error_code() {
    match program_error {
        ProgramError::Drift(ErrorCode::InsufficientCollateral) => {
            println!("Insufficient collateral for trade");
        }
        ProgramError::Other { ix_idx, code } => {
            println!("Error in instruction {}: code {}", ix_idx, code);
        }
    }
}

to_out_of_sol_error

Convert to OutOfSOL error if applicable.
pub fn to_out_of_sol_error(&self) -> Option<SdkError>
Example:
if let Some(SdkError::OutOfSOL) = sdk_error.to_out_of_sol_error() {
    println!("Need more SOL for transaction fees");
}

ProgramError

Represents errors from the Drift program.
pub enum ProgramError {
    Drift(ErrorCode),
    Other { ix_idx: u8, code: u32 },
}
Variants:
  • Drift(ErrorCode) - Error from Drift program
  • Other { ix_idx, code } - Error from another program in the transaction

ErrorCode

Drift program error codes (subset shown).
pub enum ErrorCode {
    InvalidSpotMarketAuthority,
    InsufficientDeposit,
    InsufficientCollateral,
    SufficientCollateral,
    MaxNumberOfPositions,
    MarketDelisted,
    UserHasNoPositionInMarket,
    SlippageOutsideLimit,
    OrderSizeTooSmall,
    MathError,
    ExchangePaused,
    InsufficientCollateralForSettlingPnl,
    InvalidOrderNotRiskReducing,
    OrderAmountTooSmall,
    OrderDoesNotExist,
    OrderNotTriggerable,
    OrderMustBeTriggeredFirst,
    OrderNotOpen,
    OrderWouldBeLiquidated,
    UserOrderIdAlreadyInUse,
    // ... many more
}
See the Drift program documentation for a complete list.

Error Handling Examples

Basic Error Handling

use drift_rs::{DriftClient, SdkError};

match drift_client.place_perp_order(order_params).await {
    Ok(signature) => {
        println!("Order placed: {}", signature);
    }
    Err(e) => {
        eprintln!("Error placing order: {}", e);
    }
}

Handling Specific Errors

match drift_client.place_perp_order(order_params).await {
    Ok(sig) => println!("Success: {}", sig),
    Err(SdkError::OutOfSOL) => {
        println!("Need more SOL for fees");
    }
    Err(SdkError::NoMarketData(market_id)) => {
        println!("Subscribe to market {:?} first", market_id);
    }
    Err(e) => {
        if let Some(program_err) = e.to_anchor_error_code() {
            println!("Program error: {}", program_err);
        } else {
            eprintln!("Other error: {}", e);
        }
    }
}

Retry Logic

use drift_rs::SdkError;

let mut retries = 0;
let max_retries = 3;

loop {
    match drift_client.get_user_account(&user_pubkey).await {
        Ok(user) => break Ok(user),
        Err(SdkError::Rpc(_)) if retries < max_retries => {
            retries += 1;
            println!("RPC error, retrying... ({}/{})", retries, max_retries);
            tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
        }
        Err(e) => break Err(e),
    }
}

Build docs developers (and LLMs) love