{"record":{"id":"db049229d9630d72","repo":"nautechsystems/nautilus_trader","slug":"oracle-price-required-for-market-orders","errorCode":null,"errorMessage":"Oracle price required for market orders","messagePattern":"Oracle price required for market orders","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/dydx/src/grpc/order.rs","lineNumber":175,"sourceCode":"        result\n            .to_u64()\n            .ok_or_else(|| anyhow::anyhow!(\"Failed to convert quantity to u64\"))\n    }\n\n    /// A `round`-like function that quantizes a `value` to the `fraction`.\n    fn quantize(value: &Decimal, fraction: &Decimal) -> Decimal {\n        (value / fraction).round() * fraction\n    }\n\n    /// Compute worst-case subticks for a market order using oracle price + slippage.\n    ///\n    /// # Errors\n    ///\n    /// Returns an error if oracle price is not available or conversion fails.\n    pub fn market_order_subticks(&self, side: OrderSide) -> Result<u64, anyhow::Error> {\n        let oracle = self\n            .oracle_price\n            .ok_or_else(|| anyhow::anyhow!(\"Oracle price required for market orders\"))?;\n        let worst_price = match side {\n            OrderSide::Buy => oracle * (Decimal::ONE + DEFAULT_MARKET_ORDER_SLIPPAGE),\n            OrderSide::Sell => oracle * (Decimal::ONE - DEFAULT_MARKET_ORDER_SLIPPAGE),\n            _ => oracle,\n        };\n        self.quantize_price(worst_price)\n    }\n\n    /// Get orderbook pair id.\n    #[must_use]\n    pub fn clob_pair_id(&self) -> u32 {\n        self.clob_pair_id\n    }\n}\n\n/// [`Order`] builder.\n///\n/// Note that the price input to the `OrderBuilder` is in the \"common\" units of the perpetual/currency,","sourceCodeStart":157,"sourceCodeEnd":193,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/dydx/src/grpc/order.rs#L157-L193","documentation":"Market orders on dYdV v4 are submitted as limit orders at a worst-case price derived from the oracle price plus a slippage buffer. This error is thrown when the builder has no oracle price set, so the worst-case subticks price cannot be computed.","triggerScenarios":"Calling market_order_subticks (or building a Market / StopMarket / MarketIfTouched order via OrderBuilder::build) when OrderBuilder.oracle_price is None.","commonSituations":"Submitting a market order before subscribing to or fetching the market's oracle/price data; a race where the price feed has not delivered the first update yet; cache miss in the price provider; building an order in a disconnected or cold-start state.","solutions":["Set the oracle price on the builder (or ensure the adapter populates it from the price cache) before building market orders","Wait until a price for the instrument exists (check the cache) and retry","Fall back to a bounded limit order at a manually supplied price if oracle data is unavailable","Verify the instrument id matches the one the oracle publishes for, so the lookup is not silently empty"],"exampleFix":"// before\nlet order = OrderBuilder::new(params)\n    .order_type(OrderType::Market)\n    .side(OrderSide::Buy)\n    .build()?;\n// after\nlet oracle = price_cache.get(params.clob_pair_id)\n    .ok_or_else(|| anyhow::anyhow!(\"no oracle price yet for {}\", params.clob_pair_id))?;\nlet order = OrderBuilder::new(params)\n    .order_type(OrderType::Market)\n    .side(OrderSide::Buy)\n    .oracle_price(oracle)\n    .build()?;","handlingStrategy":"validation","validationCode":"let oracle = price_cache.get(instrument_id)\n    .ok_or_else(|| anyhow::anyhow!(\"oracle price unavailable for {}\", instrument_id))?;\nanyhow::ensure!(oracle > Decimal::ZERO, \"oracle price must be positive\");","typeGuard":"fn has_oracle_price(b: &OrderBuilder) -> bool {\n    b.oracle_price.map(|p| p > Decimal::ZERO).unwrap_or(false)\n}","tryCatchPattern":"match builder.build() {\n    Ok(order) => submit(order).await?,\n    Err(e) if e.to_string().contains(\"Oracle price required\") => {\n        // defer order until price feed warms up\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Wait for at least one oracle/price update before allowing market orders","Check price cache freshness before submitting market orders","Fall back to a limit order with an explicit price when oracle data is missing"],"tags":["dydx","market-order","missing-price","precondition"],"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"}