nautechsystems/nautilus_trader · error · anyhow::Error

Invalid delta: action {action} when size zero, check size_pr

Error message

Invalid delta: action {action} when size zero, check size_precision ({size_precision}) vs data; {data:?}

What it means

While parsing a Tardis CSV row into an `OrderBookDelta`, the only legal action for a row with zero size is `Delete` (a level removal). Any other action (Add/Update) with size zero is contradictory — most often the CSV size was misparsed because the configured `size_precision` does not match the data, e.g. a value smaller than 10^-precision truncates to zero. The parser fails fast to avoid emitting a corrupt book delta.

Source

Thrown at crates/adapters/tardis/src/csv/mod.rs:224

) -> anyhow::Result<OrderBookDelta> {
    let instrument_id = match instrument_id {
        Some(id) => id,
        None => parse_instrument_id(&data.exchange, data.symbol),
    };

    let side = parse_order_side(&data.side);
    let price = parse_price(data.price, price_precision);
    let size = Quantity::new(data.amount, size_precision);
    let order_id = 0; // Not applicable for L2 data
    let order = BookOrder::new(side, price, size, order_id);

    let action = parse_book_action(data.is_snapshot, size.as_f64());
    let flags = 0; // Will be set later if needed
    let sequence = 0; // Sequence not available
    let ts_event = parse_timestamp(data.timestamp);
    let ts_init = parse_timestamp(data.local_timestamp);

    anyhow::ensure!(
        !(action != BookAction::Delete && size.is_zero()),
        "Invalid delta: action {action} when size zero, check size_precision ({size_precision}) vs data; {data:?}"
    );

    Ok(OrderBookDelta::new(
        instrument_id,
        action,
        order,
        flags,
        sequence,
        ts_event,
        ts_init,
    ))
}

fn parse_quote_record(
    data: &TardisQuoteRecord,
    price_precision: u8,

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Increase `size_precision` on the instrument definition so the CSV sizes parse to non-zero values (e.g. precision 8 instead of 2).
  2. Inspect the offending row (`data` is included in the message) and confirm the `size` column against the Tardis dataset spec.
  3. Re-export or repair the CSV if the size column is genuinely empty/corrupted.
  4. If your provider intentionally emits zero-size updates, confirm you are using a dataset/action mapping that matches (deletes vs zero-size updates).

Example fix

// before
let instrument = define_instrument(size_precision: 2, ...);
// after: match precision to the CSV data
let instrument = define_instrument(size_precision: 8, ...);
Defensive patterns

Strategy: validation

Validate before calling

def check_size_precision(instrument_precision: int, csv_min_size: str) -> None:
    from decimal import Decimal
    smallest = Decimal(csv_min_size)
    if smallest != 0 and smallest.as_tuple().exponent < -instrument_precision:
        raise ValueError(
            f"size_precision={instrument_precision} too coarse; CSV has sizes down to {smallest}"
        )

Try / catch

try:
    deltas = load_deltas(path, instrument)
except Exception as e:
    if "Invalid delta" in str(e):
        # size_precision mismatch: rebuild instrument with finer precision
        instrument = rebuild_instrument(size_precision=8)
        deltas = load_deltas(path, instrument)
    else:
        raise

Prevention

When it happens

Trigger: Calling `parse_delta_record` (directly or via `load_deltas`, the stream iterator `next`, or `fill_pending_batches`) on a Tardis book CSV row whose parsed size is 0 while the derived action is Add or Update — typically when `size_precision` in the instrument definition is coarser than the actual CSV values.

Common situations: Reusing instrument definitions with a mismatched `size_precision` for a different market; a Tardis dataset change altering size granularity; a truncated or corrupted CSV row where the size column is empty/zero.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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