{"record":{"id":"d75cfd49ca1a0cd0","repo":"nautechsystems/nautilus_trader","slug":"invalid-delta-action-action-when-size-zero-che","errorCode":null,"errorMessage":"Invalid delta: action {action} when size zero, check size_precision ({size_precision}) vs data; {data:?}","messagePattern":"Invalid delta: action (.+?) when size zero, check size_precision \\((.+?)\\) vs data; (.+?)","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/tardis/src/csv/mod.rs","lineNumber":224,"sourceCode":") -> anyhow::Result<OrderBookDelta> {\n    let instrument_id = match instrument_id {\n        Some(id) => id,\n        None => parse_instrument_id(&data.exchange, data.symbol),\n    };\n\n    let side = parse_order_side(&data.side);\n    let price = parse_price(data.price, price_precision);\n    let size = Quantity::new(data.amount, size_precision);\n    let order_id = 0; // Not applicable for L2 data\n    let order = BookOrder::new(side, price, size, order_id);\n\n    let action = parse_book_action(data.is_snapshot, size.as_f64());\n    let flags = 0; // Will be set later if needed\n    let sequence = 0; // Sequence not available\n    let ts_event = parse_timestamp(data.timestamp);\n    let ts_init = parse_timestamp(data.local_timestamp);\n\n    anyhow::ensure!(\n        !(action != BookAction::Delete && size.is_zero()),\n        \"Invalid delta: action {action} when size zero, check size_precision ({size_precision}) vs data; {data:?}\"\n    );\n\n    Ok(OrderBookDelta::new(\n        instrument_id,\n        action,\n        order,\n        flags,\n        sequence,\n        ts_event,\n        ts_init,\n    ))\n}\n\nfn parse_quote_record(\n    data: &TardisQuoteRecord,\n    price_precision: u8,","sourceCodeStart":206,"sourceCodeEnd":242,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/tardis/src/csv/mod.rs#L206-L242","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Increase `size_precision` on the instrument definition so the CSV sizes parse to non-zero values (e.g. precision 8 instead of 2).","Inspect the offending row (`data` is included in the message) and confirm the `size` column against the Tardis dataset spec.","Re-export or repair the CSV if the size column is genuinely empty/corrupted.","If your provider intentionally emits zero-size updates, confirm you are using a dataset/action mapping that matches (deletes vs zero-size updates)."],"exampleFix":"// before\nlet instrument = define_instrument(size_precision: 2, ...);\n// after: match precision to the CSV data\nlet instrument = define_instrument(size_precision: 8, ...);","handlingStrategy":"validation","validationCode":"def check_size_precision(instrument_precision: int, csv_min_size: str) -> None:\n    from decimal import Decimal\n    smallest = Decimal(csv_min_size)\n    if smallest != 0 and smallest.as_tuple().exponent < -instrument_precision:\n        raise ValueError(\n            f\"size_precision={instrument_precision} too coarse; CSV has sizes down to {smallest}\"\n        )","typeGuard":null,"tryCatchPattern":"try:\n    deltas = load_deltas(path, instrument)\nexcept Exception as e:\n    if \"Invalid delta\" in str(e):\n        # size_precision mismatch: rebuild instrument with finer precision\n        instrument = rebuild_instrument(size_precision=8)\n        deltas = load_deltas(path, instrument)\n    else:\n        raise","preventionTips":["Match instrument size_precision to the finest granularity in the Tardis dataset spec","Pre-scan the CSV for zero-size non-delete rows before full conversion","Re-derive instrument definitions when switching datasets, never reuse blindly"],"tags":["rust","csv","data-integrity","orderbook"],"backgroundTag":"internal-invariant-violation","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}