{"record":{"id":"e9cb1e4dd9f7a24c","repo":"nautechsystems/nautilus_trader","slug":"cannot-process-partial-quote-for-instrument-id-e9cb1e","errorCode":null,"errorMessage":"Cannot process partial quote for {instrument_id}: missing ask_size and no cached value","messagePattern":"Cannot process partial quote for (.+?): missing ask_size and no cached value","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/common/src/cache/quote.rs","lineNumber":146,"sourceCode":"            anyhow::bail!(\n                \"Cannot process partial quote for {instrument_id}: missing bid_price and no cached value\"\n            );\n        };\n\n        let Some(ask_price) = ask_price.or_else(|| cached.map(|quote| quote.ask_price)) else {\n            anyhow::bail!(\n                \"Cannot process partial quote for {instrument_id}: missing ask_price and no cached value\"\n            );\n        };\n\n        let Some(bid_size) = bid_size.or_else(|| cached.map(|quote| quote.bid_size)) else {\n            anyhow::bail!(\n                \"Cannot process partial quote for {instrument_id}: missing bid_size and no cached value\"\n            );\n        };\n\n        let Some(ask_size) = ask_size.or_else(|| cached.map(|quote| quote.ask_size)) else {\n            anyhow::bail!(\n                \"Cannot process partial quote for {instrument_id}: missing ask_size and no cached value\"\n            );\n        };\n\n        let quote = QuoteTick::new(\n            instrument_id,\n            bid_price,\n            ask_price,\n            bid_size,\n            ask_size,\n            ts_event,\n            ts_init,\n        );\n\n        self.quotes.insert(instrument_id, quote);\n\n        Ok(quote)\n    }","sourceCodeStart":128,"sourceCodeEnd":164,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/common/src/cache/quote.rs#L128-L164","documentation":"Partial-quote merge guard in the quote cache's process: a new BBO update omitted ask_size and no previously cached quote exists for the instrument, so a complete QuoteTick cannot be assembled and the update is rejected.","triggerScenarios":"First call to process for an instrument (or after clear()) with ask_size=None while the other three fields are provided.","commonSituations":"Cold-start or post-reconnect delta feeds omitting ask size; feeds whose initial tick carries only prices and bid size; size-less quote sources that skip optional size fields on the first message.","solutions":["Ensure the first quote per instrument includes all four fields (bid/ask price and size)","Buffer partial updates until a complete quote seeds the cache","Provide an explicit ask_size when no cached value exists"],"exampleFix":"// before\nquote_cache.process(instrument_id, bid, ask, bid_size, None, ts_event, ts_init)?;\n// after\nif !quote_cache.contains(&instrument_id) { return Ok(()); } // wait for full quote\nquote_cache.process(instrument_id, bid, ask, bid_size, None, ts_event, ts_init)?;","handlingStrategy":"try-catch","validationCode":"fn can_process(cache: &QuoteCache, id: &InstrumentId, ask_size: Option<Quantity>) -> bool {\n    ask_size.is_some() || cache.contains(id)\n}","typeGuard":null,"tryCatchPattern":"match quote_cache.process(instrument_id, bid_price, ask_price, bid_size, ask_size, ts_event, ts_init) {\n    Ok(quote) => /* forward quote */,\n    Err(e) if e.to_string().contains(\"missing ask_size\") => { /* skip partial update */ }\n    Err(e) => return Err(e.into()),\n}","preventionTips":["Seed the cache with a full quote before streaming partial updates","Log and count skipped partials per instrument to detect feeds that never send complete quotes"],"tags":["market-data","quotes","cache","missing-data","rust"],"backgroundTag":"missing-required-argument","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"}