{"record":{"id":"113a7bda60c35aea","repo":"nautechsystems/nautilus_trader","slug":"invalid-zero-size-for-action","errorCode":null,"errorMessage":"Invalid zero size for {action}","messagePattern":"Invalid zero size for (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/tardis/src/machine/parse.rs","lineNumber":493,"sourceCode":"    level: &BookLevel,\n    is_snapshot: bool,\n    ts_event: UnixNanos,\n    ts_init: UnixNanos,\n) -> anyhow::Result<OrderBookDelta> {\n    let amount = normalize_amount(level.amount, size_precision);\n    let action = parse_book_action(is_snapshot, amount);\n    let price = Price::new(level.price, price_precision);\n    let size = Quantity::new(amount, size_precision);\n    let order_id = 0; // Not applicable for L2 data\n    let order = BookOrder::new(side, price, size, order_id);\n    let flags = if is_snapshot {\n        RecordFlag::F_SNAPSHOT as u8\n    } else {\n        0\n    };\n    let sequence = 0; // Not available\n\n    anyhow::ensure!(\n        !(action != BookAction::Delete && size.is_zero()),\n        \"Invalid zero size for {action}\"\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\n/// Parse a book snapshot message into a quote tick, returning an error on invalid data.\n/// Parse a book snapshot message into a quote tick.\n///","sourceCodeStart":475,"sourceCodeEnd":511,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/tardis/src/machine/parse.rs#L475-L511","documentation":"When parsing a Tardis order book level, only a Delete action may carry a zero size. Any other action (Add/Update) with size == 0 is considered corrupt input, so parse_book_level rejects it via anyhow::ensure! before constructing the OrderBookDelta.","triggerScenarios":"parse_book_msg_as_deltas -> parse_book_level receiving a Tardis book record with action != 'delete' and size == 0 (or PriceSize parsed from a record whose size field is 0/null).","commonSituations":"Corrupt or non-conformant Tardis data files; venue-specific anomalies in recorded L2/L3 streams; a Tardis schema change emitting zero-size updates for non-delete actions.","solutions":["Pre-filter Tardis book records where action != 'delete' and size == 0 before feeding the machine parser.","Treat such records as deletes if that matches the venue semantics (set action to delete instead of add/update).","Re-download the affected Tardis data range; the record may be corrupt in the source capture.","If legitimate for a venue, update the adapter's normalization (map zero-size non-delete to Delete) upstream of this check."],"exampleFix":"// before\nanyhow::ensure!(!(action != BookAction::Delete && size.is_zero()), \"Invalid zero size for {action}\");\n// after\nlet action = if action != BookAction::Delete && size.is_zero() {\n    tracing::debug!(\"Coercing zero-size {action} to Delete\");\n    BookAction::Delete\n} else {\n    action\n};","handlingStrategy":"validation","validationCode":"// filter Tardis book levels before parsing\nlevels.retain(|lvl| lvl.action == \"delete\" || lvl.size > 0);","typeGuard":"fn is_valid_level(lvl: &BookLevel) -> bool { lvl.action == BookAction::Delete || !lvl.size.is_zero() }","tryCatchPattern":null,"preventionTips":["Sanitize Tardis captures (drop or coerce zero-size non-delete records) before feeding the machine.","Re-download data ranges that trigger parse failures — they are often corrupt at source.","Log skipped records to spot venue-specific anomalies early."],"tags":["rust","order-book","data-parsing","tardis","validation"],"backgroundTag":"invalid-argument-value","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}