Skip to main content

Error Types

All SDK errors are variants of KrakenError:
pub enum KrakenError {
    // Connection
    ConnectionFailed { url: String, reason: String },
    WebSocket(String),
    Timeout,

    // Data
    InvalidJson { message: String, raw: String },
    ChecksumMismatch { symbol: String, expected: u32, computed: u32 },

    // Subscription
    SubscriptionRejected { channel: String, reason: String },

    // Rate Limiting
    RateLimited { retry_after: Duration },

    // API
    ApiError { code: i32, message: String, raw: String, recovery: RecoveryHint },

    // Auth
    AuthenticationFailed { reason: String },
    TokenExpired,

    // Trading
    OrderRejected { reason: String },
    InsufficientFunds,
}

Basic Handling

match client.connect().await {
    Ok(client) => { /* success */ }
    Err(KrakenError::ConnectionFailed { url, reason }) => {
        log::error!("Failed to connect to {}: {}", url, reason);
    }
    Err(KrakenError::AuthenticationFailed { reason }) => {
        log::error!("Auth failed: {}", reason);
    }
    Err(e) => {
        log::error!("Unexpected error: {:?}", e);
    }
}

Retry Logic

if let Err(e) = some_operation() {
    if e.is_retryable() {
        let delay = e.retry_after().unwrap_or(Duration::from_secs(1));
        tokio::time::sleep(delay).await;
        // Retry operation
    } else {
        // Permanent failure
        return Err(e);
    }
}

Error Categories

These errors may succeed on retry:
ErrorRecovery
ConnectionFailedWait and retry
RateLimitedWait retry_after duration
WebSocket (some)Reconnect
TimeoutRetry with backoff
if error.is_retryable() {
    let delay = error.retry_after().unwrap_or(Duration::from_secs(1));
    tokio::time::sleep(delay).await;
}

Production Pattern

async fn run_with_retry<F, T, E>(
    operation: F,
    max_attempts: u32,
) -> Result<T, E>
where
    F: Fn() -> Future<Output = Result<T, E>>,
    E: IsRetryable,
{
    let mut attempts = 0;
    let mut delay = Duration::from_millis(100);

    loop {
        match operation().await {
            Ok(result) => return Ok(result),
            Err(e) if e.is_retryable() && attempts < max_attempts => {
                attempts += 1;
                let wait = e.retry_after().unwrap_or(delay);
                log::warn!("Attempt {} failed, retrying in {:?}", attempts, wait);
                tokio::time::sleep(wait).await;
                delay = (delay * 2).min(Duration::from_secs(30));
            }
            Err(e) => return Err(e),
        }
    }
}

Best Practices

Log Everything

Always log the full error, including raw fields for API errors.

Use is_retryable()

Don’t hardcode retry logic. Use the built-in classification.

Handle BufferOverflow

This event means your handler is too slow. Optimize or filter.

Don't Swallow Errors

At minimum, log errors you don’t handle. Silent failures kill systems.