{"record":{"id":"bc25546886bae1e8","repo":"nautechsystems/nautilus_trader","slug":"limit-order-must-have-a-price","errorCode":null,"errorMessage":"Limit order must have a price","messagePattern":"Limit order must have a price","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/execution/src/matching_engine/mod.rs","lineNumber":4280,"sourceCode":"                                    self.target_ask = self.core.ask;\n                                    self.target_last = self.core.last;\n                                    self.core.set_bid_raw(target_price);\n                                    self.core.set_last_raw(target_price);\n                                    fill.0 = target_price;\n                                }\n                            }\n                        }\n                    }\n                }\n\n                self.apply_liquidity_consumption(\n                    fills,\n                    order.order_side(),\n                    order.leaves_qty(),\n                    book_prices_ref,\n                )\n            }\n            None => panic!(\"Limit order must have a price\"),\n        }\n    }\n\n    fn determine_market_price_and_volume(&self, order: &OrderAny) -> Vec<(Price, Quantity)> {\n        let price = match order.order_side() {\n            OrderSide::Buy => Price::max(FIXED_PRECISION),\n            OrderSide::Sell => Price::min(FIXED_PRECISION),\n        };\n\n        // When liquidity consumption is enabled, get ALL crossed levels so that\n        // consumed levels can be filtered out while still finding valid ones.\n        let mut fills = if self.config.liquidity_consumption {\n            let size_prec = self.instrument.size_precision();\n            self.book\n                .get_all_crossed_levels(order.order_side(), price, size_prec)\n        } else {\n            let book_order = BookOrder::new(order.order_side(), price, order.quantity(), 0);\n            self.book.simulate_fills(&book_order)","sourceCodeStart":4262,"sourceCodeEnd":4298,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/execution/src/matching_engine/mod.rs#L4262-L4298","documentation":"The matching engine's order-filling path matched a LIMIT order whose price is None. A limit order is defined by its price; without one the engine cannot determine the book price level to fill against, so it panics. This invariant failure means a malformed limit order reached the fill logic instead of being rejected earlier.","triggerScenarios":"Calling the limit fill routine (determine_price_and_volume-style path around matching_engine/mod.rs:4280) with an OrderAny of type Limit whose price() returns None (match arm `None => panic!(...)`).","commonSituations":"Constructing a Limit order without setting price (or with price lost during deserialization/conversion); adapter code misclassifying a market order as limit; corrupt order state after cache round-trip.","solutions":["Always set a valid Price when creating a LIMIT order (use instrument.make_price(...) to get correct precision).","Add a pre-submission check that limit orders carry a price so they are rejected at the strategy/client layer instead of panicking in the engine.","Check serialization/deserialization of orders (e.g. redis-backed caches) so the price field is not dropped.","Verify order_type classification in adapter conversions between venue and Nautilus order types."],"exampleFix":"// before\nOrderFactory::limit(instrument_id, OrderSide::Buy, qty) // price omitted\n// after\nlet price = instrument.make_price(100.25);\nOrderFactory::limit(instrument_id, OrderSide::Buy, qty, Price(price))","handlingStrategy":"validation","validationCode":"if order.order_type() == OrderType::Limit && order.price().is_none() {\n    return Err(anyhow!(\"limit order {} missing price\", order.client_order_id()));\n}","typeGuard":"fn limit_has_price(order: &OrderAny) -> bool {\n    order.order_type() != OrderType::Limit || order.price().is_some()\n}","tryCatchPattern":null,"preventionTips":["Use instrument.make_price(...) when constructing limit orders to guarantee valid precision and value.","Validate order invariants at the strategy layer before submission.","Check that cache/serialization round-trips preserve the price field.","In adapters, never emit Limit orders derived from price-less venue messages."],"tags":["rust","matching-engine","limit-order","panic"],"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"}