{"record":{"id":"8e1c283f12fc0b38","repo":"nautechsystems/nautilus_trader","slug":"bid-required-8e1c28","errorCode":null,"errorMessage":"Bid required","messagePattern":"Bid required","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/execution/src/trailing.rs","lineNumber":136,"sourceCode":"    };\n\n    match trigger_type {\n        TriggerType::LastPrice | TriggerType::MarkPrice => {\n            let last = last.ok_or(OrderError::InvalidStateTransition)?;\n            let cand_trigger = compute(trailing_offset, last)?;\n            new_trigger_price = maybe_move(&mut trigger_price, cand_trigger, better_trigger);\n\n            if order_type == OrderType::TrailingStopLimit {\n                let limit_offset = order.limit_offset().ok_or_else(|| {\n                    anyhow::anyhow!(\"Missing `limit_offset` for trailing stop limit calculation\")\n                })?;\n                let cand_limit = compute(limit_offset, last)?;\n                new_limit_price = maybe_move(&mut limit_price, cand_limit, better_limit);\n            }\n        }\n        TriggerType::Default | TriggerType::BidAsk | TriggerType::LastOrBidAsk => {\n            let (bid, ask) = (\n                bid.ok_or_else(|| anyhow::anyhow!(\"Bid required\"))?,\n                ask.ok_or_else(|| anyhow::anyhow!(\"Ask required\"))?,\n            );\n            let basis = match order_side {\n                OrderSide::Buy => ask,\n                OrderSide::Sell => bid,\n            };\n            let cand_trigger = compute(trailing_offset, basis)?;\n            new_trigger_price = maybe_move(&mut trigger_price, cand_trigger, better_trigger);\n\n            if order_type == OrderType::TrailingStopLimit {\n                let limit_offset = order.limit_offset().ok_or_else(|| {\n                    anyhow::anyhow!(\"Missing `limit_offset` for trailing stop limit calculation\")\n                })?;\n                let cand_limit = compute(limit_offset, basis)?;\n                new_limit_price = maybe_move(&mut limit_price, cand_limit, better_limit);\n            }\n\n            if trigger_type == TriggerType::LastOrBidAsk {","sourceCodeStart":118,"sourceCodeEnd":154,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/execution/src/trailing.rs#L118-L154","documentation":"For `TriggerType::Default`, `BidAsk`, or `LastOrBidAsk`, the trailing calculation is based on the current bid/ask quotes; the function requires both. The `bid: Option<Price>` argument was `None`, so no basis price exists to apply the trailing offset against and the call fails with 'Bid required'.","triggerScenarios":"Calling `trailing_stop_calculate`/`update_trailing_stop_order` with `trigger_type` in {Default, BidAsk, LastOrBidAsk} while passing `bid: None` — e.g. no book top available for the instrument at update time.","commonSituations":"Running the update before the first quote arrives for the instrument; subscribing to trade/last-price data only while the order's trigger type needs quotes; a data outage or stale feed clearing the cached bid; an illiquid symbol with one-sided book where bid is absent.","solutions":["Ensure a quote subscription (bid/ask) is active for the instrument and pass the current top-of-book `bid`/`ask` to the call.","Skip the trailing update until both bid and ask are available (return early on `bid.is_none() || ask.is_none()`).","Switch the order's `trigger_type` to `LastPrice`/`MarkPrice` if quotes are not available but last-trade data is, and pass `last`.","Check data-engine quote cache before invoking; log a warning and defer the update instead of erroring."],"exampleFix":"// before\nlet (new_trigger, new_limit) = trailing_stop_calculate(increment, None, &order, None, None, None)?;\n// after\nlet (bid, ask) = (cache.bid(&instrument_id), cache.ask(&instrument_id));\nif let (Some(bid), Some(ask)) = (bid, ask) {\n    let (new_trigger, new_limit) = trailing_stop_calculate(increment, None, &order, Some(bid), Some(ask), None)?;\n}","handlingStrategy":"validation","validationCode":"fn quotes_ready(bid: Option<Price>, ask: Option<Price>, trigger_type: TriggerType) -> bool {\n    matches!(trigger_type, TriggerType::Default | TriggerType::BidAsk | TriggerType::LastOrBidAsk)\n        ? bid.is_some() && ask.is_some()\n        : true\n}","typeGuard":null,"tryCatchPattern":"match trailing_stop_calculate(increment, None, &order, bid, ask, last) {\n    Err(e) if e.to_string().contains(\"Bid required\") => {\n        log::debug!(\"deferring trailing update: no bid quote yet for {}\", order.instrument_id());\n    }\n    other => other?,\n}","preventionTips":["Subscribe to quote data for any instrument with bid/ask-triggered trailing stops before updating them.","Defer updates until both bid and ask exist in the cache instead of calling with `None`s.","Match the order's trigger type to the data you actually subscribe to (quotes vs last-trade)."],"tags":["rust","trailing-stop","missing-quote","market-data"],"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"}