{"record":{"id":"be1ab0c8604f0a15","repo":"nautechsystems/nautilus_trader","slug":"cannot-process-partial-quote-for-instrument-id","errorCode":null,"errorMessage":"Cannot process partial quote for {instrument_id}: missing bid_price and no cached value","messagePattern":"Cannot process partial quote for (.+?): missing bid_price and no cached value","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/common/src/cache/quote.rs","lineNumber":128,"sourceCode":"    /// Returns an error if:\n    /// - Any required field is `None` and there is no cached quote.\n    /// - The first quote received is incomplete (no cached values to merge with).\n    #[expect(clippy::too_many_arguments)]\n    pub fn process(\n        &mut self,\n        instrument_id: InstrumentId,\n        bid_price: Option<Price>,\n        ask_price: Option<Price>,\n        bid_size: Option<Quantity>,\n        ask_size: Option<Quantity>,\n        ts_event: UnixNanos,\n        ts_init: UnixNanos,\n    ) -> anyhow::Result<QuoteTick> {\n        let cached = self.quotes.get(&instrument_id);\n\n        // Resolve each field: use provided value or fall back to cache\n        let Some(bid_price) = bid_price.or_else(|| cached.map(|quote| quote.bid_price)) else {\n            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!(","sourceCodeStart":110,"sourceCodeEnd":146,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/common/src/cache/quote.rs#L110-L146","documentation":"QuoteCache::process merges partial quote updates with the previously cached quote for the instrument. This error means bid_price was None and there is no cached quote for the instrument, so bid_price cannot be resolved and no complete QuoteTick can be built.","triggerScenarios":"Calling process(instrument_id, None, ask_price, bid_size, ask_size, ...) as the first update for an instrument (nothing cached yet), or after cache.clear() (e.g. post-reconnect) when the next update is still partial.","commonSituations":"Feeding top-of-book delta-style feeds into a freshly started/restarted process; a reconnect that cleared the cache followed by partial updates; subscribing mid-session where the first tick omits the bid side.","solutions":["Wait for (or request) a full quote snapshot before forwarding partial updates to process","Skip partial updates until the first complete quote for that instrument has been cached","Provide an explicit bid_price instead of None when no cache entry exists","Seed the cache with a full quote before applying deltas"],"exampleFix":"// before\nquote_cache.process(instrument_id, None, ask, bid_size, ask_size, ts_event, ts_init)?;\n// after\nif quote_cache.contains(&instrument_id) {\n    quote_cache.process(instrument_id, None, ask, bid_size, ask_size, ts_event, ts_init)?;\n} // else wait for a complete quote","handlingStrategy":"try-catch","validationCode":"fn can_process(cache: &QuoteCache, id: &InstrumentId, bid_price: Option<Price>) -> bool {\n    bid_price.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 bid_price\") => {\n        // no cached quote yet: skip this partial update until a full quote arrives\n    }\n    Err(e) => return Err(e.into()),\n}","preventionTips":["Only forward partial updates once a complete quote has been cached for the instrument","After reconnection (cache cleared), wait for a full snapshot before resuming delta updates","Wrap process() and treat 'missing X and no cached value' errors as skip signals, not fatal"],"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"}