{"record":{"id":"8b451b09f1e241b4","repo":"nautechsystems/nautilus_trader","slug":"invalid-mid-price-for-cache-price","errorCode":null,"errorMessage":"Invalid mid price for Cache::price","messagePattern":"Invalid mid price for Cache::price","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/common/src/cache/mod.rs","lineNumber":7599,"sourceCode":"    /// the maximum fixed precision.\n    #[must_use]\n    pub fn price(&self, instrument_id: &InstrumentId, price_type: PriceType) -> Option<Price> {\n        match price_type {\n            PriceType::Bid => self\n                .quotes\n                .get(instrument_id)\n                .and_then(|quotes| quotes.front().map(|quote| quote.bid_price)),\n            PriceType::Ask => self\n                .quotes\n                .get(instrument_id)\n                .and_then(|quotes| quotes.front().map(|quote| quote.ask_price)),\n            PriceType::Mid => self.quotes.get(instrument_id).and_then(|quotes| {\n                quotes.front().map(|quote| {\n                    let mid = (quote.ask_price.as_decimal() + quote.bid_price.as_decimal())\n                        / Decimal::TWO;\n\n                    Price::from_decimal_dp(mid, quote.bid_price.precision + 1)\n                        .expect(\"Invalid mid price for Cache::price\")\n                })\n            }),\n            PriceType::Last => self\n                .trades\n                .get(instrument_id)\n                .and_then(|trades| trades.front().map(|trade| trade.price)),\n            PriceType::Mark => self\n                .mark_prices\n                .get(instrument_id)\n                .and_then(|marks| marks.front().map(|mark| mark.value)),\n        }\n    }\n\n    /// Gets all quotes for the `instrument_id`.\n    #[must_use]\n    pub fn quotes(&self, instrument_id: &InstrumentId) -> Option<Vec<QuoteTick>> {\n        self.quotes\n            .get(instrument_id)","sourceCodeStart":7581,"sourceCodeEnd":7617,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/common/src/cache/mod.rs#L7581-L7617","documentation":"Cache::price with PriceType::Mid computes mid = (ask + bid) / 2 from the latest QuoteTick and builds a Price at bid precision + 1. The expect panics when the resulting decimal cannot be converted to a Price — typically a negative, non-finite, or out-of-range mid value produced by malformed quote data.","triggerScenarios":"Calling cache.price(instrument_id, PriceType::Mid) when the top-of-book QuoteTick has invalid prices (e.g. ask or bid missing/zero/corrupt) such that the computed mid cannot form a valid Price.","commonSituations":"Feed handlers publishing placeholder quotes (0/0) during market close or before open; stale or corrupt quote data in the cache; instruments whose precision handling differs from expected.","solutions":["Validate the latest QuoteTick (positive, finite ask/bid) before requesting the mid price","Use Cache::try-style access or fetch the quote yourself and compute the mid with error handling","Purge or repair corrupt quotes from the cache for that instrument_id","Check the data source/adapter producing malformed quotes"],"exampleFix":"// before\nlet mid = cache.price(&instrument_id, PriceType::Mid).unwrap();\n// after\nif let Some(quote) = cache.quote_tick(&instrument_id) {\n    if quote.bid_price.as_f64() > 0.0 && quote.ask_price.as_f64() > 0.0 {\n        let mid = cache.price(&instrument_id, PriceType::Mid).unwrap();\n    }\n}","handlingStrategy":"type-guard","validationCode":"fn has_valid_quote(cache: &Cache, id: &InstrumentId) -> bool {\n    cache.quotes.get(id)\n        .and_then(|q| q.front())\n        .map(|q| q.bid_price.as_f64() > 0.0 && q.ask_price.as_f64() > 0.0\n              && q.ask_price >= q.bid_price)\n        .unwrap_or(false)\n}","typeGuard":"fn valid_quote(q: &QuoteTick) -> bool {\n    q.bid_price.as_f64() > 0.0 && q.ask_price.as_f64() > 0.0\n}","tryCatchPattern":"// Cannot catch the panic; guard the input quote instead\nif has_valid_quote(&cache, &instrument_id) {\n    let mid = cache.price(&instrument_id, PriceType::Mid).unwrap();\n} else {\n    eprintln!(\"no valid quote for {instrument_id}; skip mid price\");\n}","preventionTips":["Reject quote ticks with zero/negative or crossed prices at the feed-handler boundary","Purge stale quotes before market open/close when feeds emit placeholders","Prefer Last/Trade price fallback when mid is unavailable"],"tags":["rust","panic","pricing","data-integrity"],"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-14T05:17:10.506Z"}