nautechsystems/nautilus_trader · error

No result in expirations response

Error message

No result in expirations response

What it means

request_option_expirations requires a `result` payload from public/get_instruments-style expiration data. The HTTP call succeeded but `result` was absent/null, so expiration data cannot be extracted. Deribit omits `result` on error responses.

Source

Thrown at crates/adapters/deribit/src/http/client.rs:1952

    /// Requests traded option expirations for a settlement currency.
    ///
    /// # Errors
    ///
    /// Returns an error if the request fails.
    pub async fn request_option_expirations(
        &self,
        currency: DeribitCurrency,
    ) -> anyhow::Result<Vec<String>> {
        let params = GetExpirationsParams::new(currency.as_str(), DeribitExpirationKind::Option);
        let full_response = self
            .inner
            .get_expirations(params)
            .await
            .map_err(|e| anyhow::anyhow!(e))?;
        let response = full_response
            .result
            .ok_or_else(|| anyhow::anyhow!("No result in expirations response"))?;
        let expirations = response
            .expirations_for_currency(currency.as_str())
            .ok_or_else(|| anyhow::anyhow!("No option expirations for {currency}"))?;

        Ok(expirations.option.clone())
    }

    /// Requests position status reports for reconciliation.
    ///
    /// Fetches positions from Deribit and converts them to Nautilus [`PositionStatusReport`].
    ///
    /// # Strategy
    /// - Uses `currency=any` to fetch all positions in one call
    /// - Filters by instrument_id if provided
    ///
    /// # Errors
    ///
    /// Returns an error if the request fails or parsing fails.

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Verify the currency supports options on this Deribit environment.
  2. Check the response `error` field for the JSON-RPC error message.
  3. Use uppercase canonical currency codes (BTC, ETH, SOL, USDT, USDC).

Example fix

// before
let response = full_response
    .result
    .ok_or_else(|| anyhow::anyhow!("No result in expirations response"))?;
// after
let response = full_response.result.ok_or_else(|| {
    anyhow::anyhow!(
        "No result in expirations response for {currency} (error: {:?})",
        full_response.error
    )
})?;
Defensive patterns

Strategy: validation

Validate before calling

// Only request expirations for currencies known to list options
const OPTION_CURRENCIES: [&str; 2] = ["BTC", "ETH"];
assert!(OPTION_CURRENCIES.contains(&currency.to_uppercase().as_str()));

Try / catch

match client.request_option_expirations(currency).await {
    Ok(x) => handle(x),
    Err(e) if e.to_string().contains("No result in expirations response") => default_to_empty_expirations(currency),
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling request_option_expirations when the exchange returns an error-shaped response for the currency — invalid currency code or environment mismatch.

Common situations: Requesting a currency that does not list options on the connected environment (e.g. a fiat-only or unsupported currency), or typos in currency strings.

Understand the failure class

Background: "empty response", "returned no data", "empty embeddings": what HTTP 200-with-empty-body errors mean across libraries — this error's family across 36 libraries.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/40c0e4f8a327bd22. Report an issue: GitHub.