nautechsystems/nautilus_trader · error

Failed to parse tick size '{new_tick_size}': {e}

Error message

Failed to parse tick size '{new_tick_size}': {e}

What it means

rebuild_instrument_with_tick_size parses the new tick size string with parse_decimal_exact before rebuilding the BinaryOption's price bounds. This error is thrown when the tick-size string from a Polymarket market message is not a valid exact decimal.

Source

Thrown at crates/adapters/polymarket/src/http/parse.rs:279

        .collect()
}

/// Rebuilds an instrument with a new active tick size and canonical price precision.
///
/// All other fields are preserved from `existing`. Returns a new `InstrumentAny`.
pub fn rebuild_instrument_with_tick_size(
    existing: &InstrumentAny,
    new_tick_size: &str,
    ts_event: UnixNanos,
    ts_init: UnixNanos,
) -> anyhow::Result<InstrumentAny> {
    let bo = match existing {
        InstrumentAny::BinaryOption(b) => b,
        other => anyhow::bail!("Expected BinaryOption, was {other:?}"),
    };

    let tick_size = parse_decimal_exact(new_tick_size)
        .map_err(|e| anyhow::anyhow!("Failed to parse tick size '{new_tick_size}': {e}"))?;
    let (min_price, max_price) = tick_relative_price_bounds(tick_size)?;
    let price_increment = min_price;

    let rebuilt = BinaryOption::builder()
        .instrument_id(bo.id)
        .raw_symbol(bo.raw_symbol)
        .asset_class(bo.asset_class)
        .currency(bo.currency)
        .activation_ns(bo.activation_ns)
        .expiration_ns(bo.expiration_ns)
        .price_precision(POLYMARKET_PRICE_PRECISION)
        .size_precision(bo.size_precision)
        .price_increment(price_increment)
        .size_increment(bo.size_increment)
        .maybe_outcome(bo.outcome)
        .maybe_description(bo.description)
        .maybe_max_quantity(bo.max_quantity)
        // min_quantity: see `create_instrument_from_def`

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Log the offending new_tick_size value from the market message.
  2. Validate/normalize the tick size string before calling rebuild (trim, reject empty, parse as Decimal).
  3. Skip or defer the instrument rebuild when the tick size is unparseable, and re-sync instruments from the REST snapshot.

Example fix

// before
let tick_size = parse_decimal_exact(new_tick_size)
    .map_err(|e| anyhow::anyhow!("Failed to parse tick size '{new_tick_size}': {e}"))?;
// after
let trimmed = new_tick_size.trim();
if trimmed.is_empty() { anyhow::bail!("skip rebuild: empty tick size"); }
let tick_size = parse_decimal_exact(trimmed)
    .map_err(|e| anyhow::anyhow!("Failed to parse tick size '{new_tick_size}': {e}"))?;
Defensive patterns

Strategy: validation

Validate before calling

fn is_valid_tick_size_str(s: &str) -> bool {
    !s.trim().is_empty() && parse_decimal_exact(s.trim()).map(|d| d > Decimal::ZERO).unwrap_or(false)
}

Try / catch

match rebuild_instrument_with_tick_size(&instrument, &msg.new_tick_size) {
    Ok(updated) => updated,
    Err(e) => { warn!("tick size update rejected: {e}"); instrument.clone() }
}

Prevention

When it happens

Trigger: handle_market_message receiving a market update whose new_tick_size is empty, non-numeric, or in a format parse_decimal_exact rejects (e.g. scientific notation, thousands separators).

Common situations: Unexpected tick_size values in CLOB market channel updates, venue emitting "0" or blank during market setup, or locale-formatted numbers from a custom feed.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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