nautechsystems/nautilus_trader · error · anyhow::Error

Invalid tickSize of 0

Error message

Invalid tickSize of 0

What it means

While building a Spot CurrencyPair from the JSON exchangeInfo, decimal_price parses PRICE_FILTER.tickSize and the code then enforces it is non-zero. A literal "0" (or "0.0", normalized to zero) parses successfully but fails the ensure!, producing this short message.

Source

Thrown at crates/adapters/binance/src/common/parse.rs:800

    let price_filter = symbol
        .filters
        .iter()
        .find(|filter| filter.filter_type == "PRICE_FILTER")
        .context("Missing PRICE_FILTER in symbol filters")?;
    let lot_filter = symbol
        .filters
        .iter()
        .find(|filter| filter.filter_type == "LOT_SIZE")
        .context("Missing LOT_SIZE in symbol filters")?;

    let tick_size = decimal_price(
        price_filter
            .tick_size
            .as_deref()
            .context("Missing PRICE_FILTER tickSize")?,
    )?;
    anyhow::ensure!(!tick_size.is_zero(), "Invalid tickSize of 0");
    let step_size = decimal_quantity(
        lot_filter
            .step_size
            .as_deref()
            .context("Missing LOT_SIZE stepSize")?,
    )?;
    anyhow::ensure!(!step_size.is_zero(), "Invalid stepSize of 0");

    let instrument = CurrencyPair::new(
        InstrumentId::new(
            Symbol::from_str_unchecked(&symbol.symbol),
            Venue::new(BINANCE),
        ),
        Symbol::new(&symbol.symbol),
        get_currency(&symbol.base_asset),
        get_currency(&symbol.quote_asset),
        tick_size.precision,
        step_size.precision,

View on GitHub (pinned to a4b06ed870)

Solutions

  1. Check the live Spot exchangeInfo tickSize for the symbol.
  2. Skip symbols whose tickSize is zero during loading.
  3. Refresh cached exchangeInfo data.
  4. Report persistent zero tickSize on an actively trading pair.
Defensive patterns

Strategy: try-catch

Validate before calling

fn spot_tick_size_is_valid(symbol: &BinanceSymbolJson) -> bool {
    symbol
        .filters
        .iter()
        .find(|f| f.filter_type == "PRICE_FILTER")
        .and_then(|f| f.tick_size.as_deref())
        .map(|t| {
            rust_decimal::Decimal::from_str(t)
                .map(|d| !d.is_zero())
                .unwrap_or(false)
        })
        .unwrap_or(false)
}

Try / catch

match parse_spot_instrument_json_with_fees(&symbol, None, None, ts_event, ts_init) {
    Ok(inst) => instruments.push(inst),
    Err(e) if e.to_string().contains("Invalid tickSize of 0") => {
        tracing::warn!(symbol = %symbol.symbol, "zero tickSize, skipping")
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Spot exchangeInfo PRICE_FILTER with "tickSize": "0" for the symbol being parsed — placeholder filters on pre-listing symbols or corrupted/cached payloads.

Common situations: Pairs announced but not yet live; stale caches or replayed fixtures with zeroed filters; venue data glitches.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@a4b06ed870 (2026-08-16). Data as JSON: /api/errors/702b293fc74c9a44. Report an issue: GitHub.