{"record":{"id":"7f1cdd96f371e553","repo":"nautechsystems/nautilus_trader","slug":"take-profit-limit-order-missing-limit-price","errorCode":null,"errorMessage":"Take profit limit order missing limit price","messagePattern":"Take profit limit order missing limit price","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/dydx/src/execution/mod.rs","lineNumber":1530,"sourceCode":"                        let msg = order_builder.build_take_profit_market_order(\n                            instrument_id,\n                            client_id_u32,\n                            client_metadata,\n                            order.order_side(),\n                            trigger_price,\n                            order.quantity(),\n                            order.is_reduce_only(),\n                            cond_expire,\n                        )?;\n                        (msg, \"take_profit_market\")\n                    }\n                    // dYdX TakeProfitLimit maps to Nautilus LimitIfTouched\n                    OrderType::LimitIfTouched => {\n                        let trigger_price = order.trigger_price().ok_or_else(|| {\n                            anyhow::anyhow!(\"Take profit limit order missing trigger_price\")\n                        })?;\n                        let limit_price = order.price().ok_or_else(|| {\n                            anyhow::anyhow!(\"Take profit limit order missing limit price\")\n                        })?;\n                        let cond_expire = order.expire_time().map(nanos_to_secs_i64);\n                        let msg = order_builder.build_take_profit_limit_order(\n                            instrument_id,\n                            client_id_u32,\n                            client_metadata,\n                            order.order_side(),\n                            trigger_price,\n                            limit_price,\n                            order.quantity(),\n                            order.time_in_force(),\n                            order.is_post_only(),\n                            order.is_reduce_only(),\n                            cond_expire,\n                        )?;\n                        (msg, \"take_profit_limit\")\n                    }\n                    _ => unreachable!(\"Order type already validated\"),","sourceCodeStart":1512,"sourceCodeEnd":1548,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/dydx/src/execution/mod.rs#L1512-L1548","documentation":"This error is raised by the dYdX execution client when submitting a LimitIfTouched order (Nautilus's mapping of dYdX TakeProfitLimit) whose limit price is None. dYdX's take-profit limit order type requires both a trigger price and a limit price, so the client refuses to build the order without one.","triggerScenarios":"Calling ExecutionClient.submit_order (directly or via submit_order_list) with an order of type LimitIfTouched that was created without a price (order.price() returns None), while its trigger_price is present.","commonSituations":"Constructing a LimitIfTouched order in Python/Nautilus without passing price=...; copying an order-building snippet from a MarketIfTouched order (which has no limit price) and switching the type to LimitIfTouched; a strategy that sets trigger_price programmatically but forgets the limit price.","solutions":["Pass a limit price when creating the order: OrderFactory.limit_if_touched(instrument_id, OrderSide.BUY, qty, price=limit_px, trigger_price=trigger_px).","Verify with order.price (Python) before submitting; only use LimitIfTouched when both trigger and limit prices are set.","If you do not want a limit price, submit a MarketIfTouched order instead (dYdX maps that to a market-type take profit).","Check the instrument's tick size and round the limit price before submission."],"exampleFix":"// before: LimitIfTouched built without price -> error at submit\n// let order = factory.limit_if_touched(instrument_id, OrderSide::Buy, qty, None, Some(trigger_px), ...);\n// after\nlet order = factory.limit_if_touched(instrument_id, OrderSide::Buy, qty, Some(limit_px), Some(trigger_px), ...);","handlingStrategy":"validation","validationCode":"if order.order_type() == OrderType::LimitIfTouched {\n    assert!(order.trigger_price().is_some(), \"LIT order missing trigger price\");\n    assert!(order.price().is_some(), \"LIT order missing limit price\");\n}","typeGuard":"fn has_required_prices(order: &dyn Order) -> bool {\n    order.trigger_price().is_some() && order.price().is_some()\n}","tryCatchPattern":null,"preventionTips":["Use OrderFactory.limit_if_touched which enforces price arguments","Validate order fields (price, trigger_price) before submit_order","Prefer MarketIfTouched when no limit price is desired"],"tags":["dydx","order-submission","missing-price","validation"],"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"}