{"record":{"id":"e826c711bf16775c","repo":"nautechsystems/nautilus_trader","slug":"failed-to-deserialize-record-e","errorCode":null,"errorMessage":"Failed to deserialize record: {e}","messagePattern":"Failed to deserialize record: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/tardis/src/csv/stream.rs","lineNumber":311,"sourceCode":"            Some(Ok(self.buffer.clone()))\n        }\n    }\n}\n\nimpl DeltaStreamIterator {\n    fn read_record(&mut self) -> anyhow::Result<Option<TardisBookUpdateRecord>> {\n        if !self\n            .reader\n            .read_record(&mut self.record)\n            .map_err(|e| anyhow::anyhow!(\"Failed to read record: {e}\"))?\n        {\n            return Ok(None);\n        }\n\n        self.record\n            .deserialize::<TardisBookUpdateRecord>(None)\n            .map(Some)\n            .map_err(|e| anyhow::anyhow!(\"Failed to deserialize record: {e}\"))\n    }\n}\n\n/// Streams [`OrderBookDelta`]s from a Tardis format CSV at the given `filepath`,\n/// yielding chunks of the specified size.\n///\n/// # Precision Inference Warning\n///\n/// When using streaming with precision inference (not providing explicit precisions),\n/// the inferred precision may differ from bulk loading the entire file. This is because\n/// precision inference works within chunk boundaries, and different chunks may contain\n/// values with different precision requirements. For deterministic precision behavior,\n/// provide explicit `price_precision` and `size_precision` parameters.\n///\n/// # Errors\n///\n/// Returns an error if `chunk_size` is outside `[1, 1_000_000]`, or if the file cannot be opened,\n/// read, or parsed as CSV.","sourceCodeStart":293,"sourceCodeEnd":329,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/tardis/src/csv/stream.rs#L293-L329","documentation":"After a CSV row is successfully read in `DeltaStreamIterator::read_record`, it is deserialized into `TardisBookUpdateRecord`. If the row's fields do not match the expected Tardis book-update schema (missing/invalid columns, wrong types, unexpected values), the deserializer error is wrapped as this error. It means the file is readable but its content does not conform to the expected record shape.","triggerScenarios":"Calling the delta stream `next` on a CSV whose rows deviate from the Tardis book update schema: missing required fields (e.g. `symbol`, `timestamp`), non-numeric values in numeric columns, or a file exported by a different Tardis endpoint/version with a changed schema.","commonSituations":"Pointing the stream at an options-chain or trades CSV instead of a book updates CSV; a Tardis schema/version change; hand-edited or filtered CSVs that dropped columns.","solutions":["Confirm the file is a Tardis incremental book (derivative_ticker/book) CSV, not trades or options-chain output.","Open the failing row and compare columns against the expected `TardisBookUpdateRecord` schema (exchange, symbol, side, price, size, timestamp, local_timestamp...).","Re-export the data with the current Tardis schema if the file came from an older exporter version.","Check for NaN/empty numeric fields; fix or drop malformed rows before streaming."],"exampleFix":"// before: wrong file kind\nlet stream = DeltaStream::from_path(\"trades.csv\", ...)?;\n// after: use the matching reader for the file kind\nif is_book_csv(path) { DeltaStream::from_path(path, ...) } else { OptionsChainStream::from_path(path, ...) }","handlingStrategy":"validation","validationCode":"REQUIRED_BOOK_COLS = {\"exchange\", \"symbol\", \"side\", \"price\", \"size\", \"timestamp\", \"local_timestamp\"}\n\ndef validate_book_csv_header(path: str) -> None:\n    import csv\n    with open(path, newline=\"\") as f:\n        header = set(next(csv.reader(f)))\n    missing = REQUIRED_BOOK_COLS - header\n    if missing:\n        raise ValueError(f\"{path}: not a Tardis book CSV, missing {sorted(missing)}\")","typeGuard":"def is_book_csv(path: str) -> bool:\n    import csv\n    with open(path, newline=\"\") as f:\n        return REQUIRED_BOOK_COLS.issubset(set(next(csv.reader(f))))","tryCatchPattern":"try:\n    for batch in stream:\n        process(batch)\nexcept Exception as e:\n    if \"Failed to deserialize record\" in str(e):\n        raise DataSchemaError(f\"CSV does not match TardisBookUpdateRecord schema: {e}\") from e\n    raise","preventionTips":["Validate the CSV header against the expected schema before streaming","Feed each record kind (book/trades/options-chain) to its matching stream type","Re-export old datasets when the Tardis schema version changes; never concatenate mismatched exports"],"tags":["rust","csv","deserialization","schema"],"backgroundTag":"schema-validation-failed","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"}