nautechsystems/nautilus_trader · error · anyhow::Error

invalid {field} `{raw}`: {e}

Error message

invalid {field} `{raw}`: {e}

What it means

A quantity field from a Binance Spot market-data event (book ticker, depth diff, kline) is negative or could not be converted to a `Quantity` at the required precision. `parse_non_negative_quantity` parses the string as a `Decimal`, rejects sign-negative values, then converts at the given precision; failures carry the underlying conversion error `{e}`.

Source

Thrown at crates/adapters/binance/src/spot/websocket/public_json/parse.rs:66

fn parse_positive_price(raw: &str, precision: u8, field: &str) -> anyhow::Result<Price> {
    parse_price_at_precision(raw, precision)
        .ok_or_else(|| anyhow::anyhow!("invalid {field} `{raw}`"))
}

fn parse_positive_quantity(raw: &str, precision: u8, field: &str) -> anyhow::Result<Quantity> {
    parse_quantity_at_precision(raw, precision)
        .ok_or_else(|| anyhow::anyhow!("invalid {field} `{raw}`"))
}

fn parse_non_negative_quantity(raw: &str, precision: u8, field: &str) -> anyhow::Result<Quantity> {
    let decimal = Decimal::from_str(raw).with_context(|| format!("invalid {field} `{raw}`"))?;
    if decimal.is_sign_negative() {
        anyhow::bail!("invalid {field} `{raw}`");
    }

    Quantity::from_decimal_dp(decimal, precision)
        .map_err(|e| anyhow::anyhow!("invalid {field} `{raw}`: {e}"))
}

/// Parses a trade message into a `TradeTick`.
///
/// # Errors
///
/// Returns an error if price or quantity fields cannot be parsed.
pub fn parse_trade(
    msg: &BinanceSpotTradeMsg,
    instrument: &InstrumentAny,
    ts_init: UnixNanos,
) -> anyhow::Result<TradeTick> {
    let instrument_id = instrument.id();
    let price_precision = instrument.price_precision();
    let size_precision = instrument.size_precision();

    let price = parse_positive_price(&msg.price, price_precision, "trade price")?;
    let size = parse_positive_quantity(&msg.quantity, size_precision, "trade quantity")?;

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Refresh instrument definitions so the configured precision matches what Binance sends for the symbol.
  2. Inspect the logged message (`invalid {field} \`{raw}\`: {e}`) to see the exact offending value and conversion error.
  3. Apply depth diffs in the correct order (or resync via a depth snapshot) so negative quantities do not appear.
  4. Guard stream processing to skip malformed events and reconnect/resync depth rather than aborting.

Example fix

// before: applying depth diffs from a stale buffer -> negative quantity
// after: resync when a diff's UpdateFinalFailedEvent / sequence gap is detected
if msg.final_update_id < last_update_id + 1 { depth_client.resync(symbol).await?; }
Defensive patterns

Strategy: validation

Validate before calling

fn valid_non_negative_quantity(raw: &str, precision: u8) -> bool {
    raw.parse::<rust_decimal::Decimal>()
        .map(|d| !d.is_sign_negative() && d.scale() <= u32::from(precision))
        .unwrap_or(false)
}

Prevention

When it happens

Trigger: A book ticker, depth diff, or kline message contains a quantity string like `"-0.5"`, an unparseable value, or a decimal whose scale exceeds the instrument precision so `Quantity::from_decimal_dp` fails with an overflow/rounding error.

Common situations: Corrupt or out-of-order depth diffs with negative deltas applied incorrectly; stale instrument precision metadata; Binance format changes; a kline with a negative base-asset volume field.

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/42a7dcf08cb46d99. Report an issue: GitHub.