nautechsystems/nautilus_trader · error
Missing ask quote for pair {pair}
Error message
Missing ask quote for pair {pair} What it means
The exchange-rate graph builder pairs each bid quote with its matching ask quote from quotes_ask. This error means a pair exists in the bid map but has no corresponding entry in the ask map, so a two-sided quote cannot be constructed for that currency pair.
Source
Thrown at crates/common/src/xrate.rs:73
}
if quotes_bid.len() != quotes_ask.len() {
anyhow::bail!("Quote maps must have equal lengths");
}
// Validated here, in the same position as the price-type match this replaced, so the
// identical-currency shortcut and the quote-map errors keep their original precedence.
if !matches!(price_type, PriceType::Bid | PriceType::Ask | PriceType::Mid) {
anyhow::bail!("Invalid `price_type`, was '{price_type}'");
}
// Construct a graph: each currency maps to its neighbors and corresponding conversion rate
let mut graph: AHashMap<Ustr, Vec<(Ustr, Decimal)>> = AHashMap::new();
for (pair, bid) in quotes_bid {
let ask = quotes_ask
.remove(&pair)
.ok_or_else(|| anyhow::anyhow!("Missing ask quote for pair {pair}"))?;
let parts: Vec<&str> = pair.split('/').collect();
if parts.len() != 2 {
log::warn!("Skipping invalid pair string: {pair}");
continue;
}
if bid <= Decimal::ZERO || ask <= Decimal::ZERO {
// Both sides are required to build valid forward and reverse edges.
log::warn!("Skipping pair with non-positive bid or ask rate: {pair}");
continue;
}
let base = Ustr::from(parts[0]);
let quote = Ustr::from(parts[1]);
let (forward_rate, reverse_rate) = directional_rates(bid, ask, price_type);
graph.entry(base).or_default().push((quote, forward_rate));View on GitHub (pinned to 18893faf8b)
Solutions
- Ensure quotes_bid and quotes_ask contain identical key sets before calling get_exchange_rate.
- Filter quotes_bid to only pairs also present in quotes_ask (and vice versa) and log the skipped pairs.
- Check the data pipeline/venue for why the ask side is missing for the affected pair.
Example fix
// before
let rate = get_exchange_rate(&bid_quotes, &ask_quotes, "EUR/USD")?;
// after
let rate = if bid_quotes.keys().all(|k| ask_quotes.contains_key(k)) {
get_exchange_rate(&bid_quotes, &ask_quotes, "EUR/USD")?
} else {
let pairs: Vec<_> = bid_quotes.keys().filter(|k| !ask_quotes.contains_key(*k)).collect();
anyhow::bail!("ask quotes missing for pairs: {pairs:?}")
}; Defensive patterns
Strategy: validation
Validate before calling
let missing: Vec<_> = quotes_bid.keys().filter(|p| !quotes_ask.contains_key(*p)).collect();
if !missing.is_empty() {
return Err(format!("ask quotes missing for pairs: {missing:?}"));
} Try / catch
match get_exchange_rate(&bids, &asks, pair) {
Ok(rate) => rate,
Err(e) if e.to_string().contains("Missing ask quote") => { log::warn!("skipping {pair}: {e}"); continue; }
Err(e) => return Err(e),
} Prevention
- Build bid and ask quote maps from the same iteration over instruments.
- Log and drop one-sided quotes before invoking exchange-rate conversion.
- Monitor venue feeds for asymmetric book depth on the pairs you trade.
When it happens
Trigger: Calling get_exchange_rate with quotes_bid and quotes_ask maps of different pair coverage — e.g. a pair present in quotes_bid but absent from quotes_ask.
Common situations: Partial market data snapshots where one side of the book was not received; FX feeds that only publish one side for illiquid pairs; building the two maps in separate loops where one silently skipped an instrument.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- Cannot process partial quote for {instrument_id}: missing bi
- Cannot process partial quote for {instrument_id}: missing as
- Cannot process partial quote for {instrument_id}: missing bi
- Cannot process partial quote for {instrument_id}: missing as
- Missing data in SetFeeProtocol event log
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/17b6cd8b9b21b1b2.
Report an issue: GitHub.