{"record":{"id":"cf8dbb111dacf50a","repo":"nautechsystems/nautilus_trader","slug":"invalid-negative-order-book-update-id-cf8dbb","errorCode":null,"errorMessage":"invalid negative order-book update ID","messagePattern":"invalid negative order-book update ID","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/binance/src/spot/http/client.rs","lineNumber":3064,"sourceCode":"        }\n        let instrument = self.instrument_from_cache_by_id(instrument_id)?;\n        let params = DepthParams {\n            symbol: instrument_id.symbol.to_string(),\n            limit: depth,\n        };\n        let snapshot = self.inner.depth(&params).await?;\n        let ts_event = self.generate_ts_init();\n        Self::parse_book_snapshot_response(instrument_id, &instrument, &snapshot, ts_event)\n    }\n\n    fn parse_book_snapshot_response(\n        instrument_id: InstrumentId,\n        instrument: &InstrumentAny,\n        snapshot: &BinanceDepth,\n        ts_event: UnixNanos,\n    ) -> anyhow::Result<OrderBook> {\n        let sequence = u64::try_from(snapshot.last_update_id)\n            .map_err(|_| anyhow::anyhow!(\"invalid negative order-book update ID\"))?;\n        let mut book = OrderBook::new(instrument_id, BookType::L2_MBP);\n        let mut add_level = |level: &super::models::BinancePriceLevel,\n                             side: OrderSide,\n                             order_id: usize,\n                             name: &str|\n         -> anyhow::Result<()> {\n            let price = Price::from_mantissa_exponent_checked(\n                level.price_mantissa,\n                snapshot.price_exponent,\n                instrument.price_precision(),\n            )\n            .map_err(|e| anyhow::anyhow!(\"invalid {name} price: {e}\"))?;\n            anyhow::ensure!(price.is_positive(), \"invalid non-positive {name} price\");\n            let qty_mantissa = u64::try_from(level.qty_mantissa)\n                .map_err(|_| anyhow::anyhow!(\"invalid negative {name} quantity\"))?;\n            let quantity = Quantity::from_mantissa_exponent_checked(\n                qty_mantissa,\n                snapshot.qty_exponent,","sourceCodeStart":3046,"sourceCodeEnd":3082,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/binance/src/spot/http/client.rs#L3046-L3082","documentation":"Thrown in `parse_book_snapshot_response` when the depth snapshot's `last_update_id` is negative and cannot be converted to the unsigned `u64` sequence number required by NautilusTrader's `OrderBook`. Binance should never send a negative update ID, so this is a defensive invariant check against malformed API responses.","triggerScenarios":"Calling `request_book_snapshot` when the Binance `/api/v3/depth` response contains a negative `lastUpdateId` — essentially only possible with a corrupted, mocked, or non-conformant response payload.","commonSituations":"Proxy or MITM tooling returning synthesized/garbage depth JSON; a test fixture or mock server with negative IDs; a breaking change in the upstream API response schema.","solutions":["Inspect the raw depth response to confirm `lastUpdateId` is a non-negative integer.","Re-fetch the snapshot; a single malformed response is usually transient.","If using a proxy/mock, fix the fixture to emit valid non-negative update IDs.","Report a bug if a genuine Binance response contains a negative ID."],"exampleFix":"// before: snapshot from an untrusted source used directly\nlet book = client.request_book_snapshot(instrument_id, Some(5000)).await?;\n// after: retry on malformed snapshots\nlet book = match client.request_book_snapshot(instrument_id, Some(5000)).await {\n    Ok(b) => b,\n    Err(e) if e.to_string().contains(\"invalid negative order-book update ID\") => {\n        client.request_book_snapshot(instrument_id, Some(5000)).await?\n    }\n    Err(e) => return Err(e),\n};","handlingStrategy":"validation","validationCode":"fn has_valid_update_id(snapshot: &BinanceDepth) -> bool { snapshot.last_update_id >= 0 }","typeGuard":"fn valid_snapshot(s: &BinanceDepth) -> bool { s.last_update_id >= 0 && !s.bids.is_empty() && !s.asks.is_empty() }","tryCatchPattern":"match client.request_book_snapshot(id, depth).await {\n    Ok(book) => book,\n    Err(e) if e.to_string().contains(\"invalid negative order-book update ID\") => retry_snapshot(id, depth).await?,\n    Err(e) => return Err(e),\n}","preventionTips":["Re-fetch snapshots on parse errors rather than propagating stale data.","Avoid routing exchange traffic through proxies that rewrite payloads.","Validate fixtures/mocks emit non-negative lastUpdateId."],"tags":["orderbook","binance","validation","sequence-number"],"backgroundTag":"value-out-of-range","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"}