nautechsystems/nautilus_trader · error
Invalid mid price for Cache::price
Error message
Invalid mid price for Cache::price
What it means
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.
Source
Thrown at crates/common/src/cache/mod.rs:7599
/// the maximum fixed precision.
#[must_use]
pub fn price(&self, instrument_id: &InstrumentId, price_type: PriceType) -> Option<Price> {
match price_type {
PriceType::Bid => self
.quotes
.get(instrument_id)
.and_then(|quotes| quotes.front().map(|quote| quote.bid_price)),
PriceType::Ask => self
.quotes
.get(instrument_id)
.and_then(|quotes| quotes.front().map(|quote| quote.ask_price)),
PriceType::Mid => self.quotes.get(instrument_id).and_then(|quotes| {
quotes.front().map(|quote| {
let mid = (quote.ask_price.as_decimal() + quote.bid_price.as_decimal())
/ Decimal::TWO;
Price::from_decimal_dp(mid, quote.bid_price.precision + 1)
.expect("Invalid mid price for Cache::price")
})
}),
PriceType::Last => self
.trades
.get(instrument_id)
.and_then(|trades| trades.front().map(|trade| trade.price)),
PriceType::Mark => self
.mark_prices
.get(instrument_id)
.and_then(|marks| marks.front().map(|mark| mark.value)),
}
}
/// Gets all quotes for the `instrument_id`.
#[must_use]
pub fn quotes(&self, instrument_id: &InstrumentId) -> Option<Vec<QuoteTick>> {
self.quotes
.get(instrument_id)View on GitHub (pinned to 18893faf8b)
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
Example fix
// before
let mid = cache.price(&instrument_id, PriceType::Mid).unwrap();
// after
if let Some(quote) = cache.quote_tick(&instrument_id) {
if quote.bid_price.as_f64() > 0.0 && quote.ask_price.as_f64() > 0.0 {
let mid = cache.price(&instrument_id, PriceType::Mid).unwrap();
}
} Defensive patterns
Strategy: type-guard
Validate before calling
fn has_valid_quote(cache: &Cache, id: &InstrumentId) -> bool {
cache.quotes.get(id)
.and_then(|q| q.front())
.map(|q| q.bid_price.as_f64() > 0.0 && q.ask_price.as_f64() > 0.0
&& q.ask_price >= q.bid_price)
.unwrap_or(false)
} Type guard
fn valid_quote(q: &QuoteTick) -> bool {
q.bid_price.as_f64() > 0.0 && q.ask_price.as_f64() > 0.0
} Try / catch
// Cannot catch the panic; guard the input quote instead
if has_valid_quote(&cache, &instrument_id) {
let mid = cache.price(&instrument_id, PriceType::Mid).unwrap();
} else {
eprintln!("no valid quote for {instrument_id}; skip mid price");
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Replacement hash {transaction_hash} conflicts with another i
- Included wrap transaction {tx_hash} has invalid block number
- WETH balance overflow for included transaction {tx_hash} at
- in-flight mutex poisoned
- wallet balance mutex poisoned
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/8b451b09f1e241b4.
Report an issue: GitHub.