nautechsystems/nautilus_trader · error

Cannot calculate slippage, the spot price before is not set

Error message

Cannot calculate slippage, the spot price before is not set

What it means

SwapTradeInfo::get_slippage_bps computes slippage as (execution_price - spot_price_before)/spot_price_before * 10_000 bps. It needs a positive pre-swap spot price as the reference; if spot_price_before is zero/unset the method bails rather than divide by zero. The same guard backs the sibling price-impact calculation, and check_spot_price_before enforces it.

Source

Thrown at crates/model/src/defi/data/swap_trade_info.rs:125

    /// deviation from the spot price before the swap. This measures the total
    /// cost to the trader.
    ///
    /// # Returns
    /// Total slippage in basis points (10000 = 100%)
    ///
    /// # Errors
    ///
    /// Returns an error if the spot price before the swap is not set or is zero.
    pub fn get_slippage_bps(&self) -> anyhow::Result<u32> {
        if let Some(spot_price_before) = self.spot_price_before {
            Self::check_spot_price_before(spot_price_before, PriceMetric::Slippage)?;
            let price_change = self.execution_price - spot_price_before;
            let slippage =
                (price_change.as_decimal() / spot_price_before.as_decimal()).abs() * dec!(10_000);

            Ok(slippage.round().to_u32().unwrap_or(0))
        } else {
            anyhow::bail!("Cannot calculate slippage, the spot price before is not set")
        }
    }

    fn check_spot_price_before(
        spot_price_before: Price,
        metric: PriceMetric,
    ) -> anyhow::Result<()> {
        let metric = metric.name();
        anyhow::ensure!(
            !spot_price_before.is_zero(),
            "Cannot calculate {metric}, the spot price before is zero"
        );
        Ok(())
    }
}

enum PriceMetric {
    Impact,

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Populate spot_price_before from the pool's price before the swap (from sqrt price before the tick crossing)
  2. Skip or defer the slippage calculation when no valid pre-price is available
  3. Add a validation step in SwapTradeInfo construction so callers cannot build it without a spot price before
  4. Use check_spot_price_before / a zero check before invoking the method

Example fix

// before
let slippage = swap.get_slippage_bps(spot_before)?;
// after
anyhow::ensure!(!spot_before.is_zero(), "spot price before must be positive");
let slippage = swap.get_slippage_bps(spot_before)?;
Defensive patterns

Strategy: validation

Validate before calling

if spot_price_before.is_zero() {
    // slippage not computable without a reference price
}

Type guard

fn slippage_computable(p: &Price) -> bool { !p.is_zero() }

Try / catch

match swap.get_slippage_bps(spot_before) {
    Ok(bps) => Some(bps),
    Err(e) if e.to_string().contains("spot price before is not set") => None,
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling get_slippage_bps with spot_price_before set to zero or a default Price, e.g. when the pre-trade price was not derived from the swap's before-sqrt-price.

Common situations: Building SwapTradeInfo from partial event data missing the pre-swap price; replay scripts that start mid-stream; tests validating the zero-price rejection.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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