{"record":{"id":"afa3f78e03460fa8","repo":"nautechsystems/nautilus_trader","slug":"stop-limit-order-requires-trigger-price","errorCode":null,"errorMessage":"STOP_LIMIT order requires trigger_price","messagePattern":"STOP_LIMIT order requires trigger_price","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/coinbase/src/http/client.rs","lineNumber":1686,"sourceCode":"                            end_time: format_rfc3339_from_nanos(expire)?,\n                            post_only,\n                        },\n                    }))\n                }\n                TimeInForce::Fok => Ok(OrderConfiguration::LimitFok(LimitFok {\n                    limit_limit_fok: LimitFokParams {\n                        base_size: qty,\n                        limit_price,\n                    },\n                })),\n                _ => anyhow::bail!(\"Unsupported TIF {time_in_force} for LIMIT on Coinbase\"),\n            }\n        }\n        OrderType::StopLimit => {\n            let limit_price =\n                price.ok_or_else(|| anyhow::anyhow!(\"STOP_LIMIT order requires a price\"))?;\n            let stop_price = trigger\n                .ok_or_else(|| anyhow::anyhow!(\"STOP_LIMIT order requires trigger_price\"))?;\n            let direction = match side {\n                OrderSide::Buy => CoinbaseStopDirection::StopUp,\n                OrderSide::Sell => CoinbaseStopDirection::StopDown,\n            };\n\n            match time_in_force {\n                TimeInForce::Gtc => Ok(OrderConfiguration::StopLimitGtc(StopLimitGtc {\n                    stop_limit_stop_limit_gtc: StopLimitGtcParams {\n                        base_size: qty,\n                        limit_price,\n                        stop_price,\n                        stop_direction: direction,\n                    },\n                })),\n                TimeInForce::Gtd => {\n                    let expire = expire_time\n                        .ok_or_else(|| anyhow::anyhow!(\"GTD STOP_LIMIT requires expire_time\"))?;\n                    Ok(OrderConfiguration::StopLimitGtd(StopLimitGtd {","sourceCodeStart":1668,"sourceCodeEnd":1704,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/coinbase/src/http/client.rs#L1668-L1704","documentation":"A STOP_LIMIT order on Coinbase needs both the limit price and the stop (trigger) price. This guard fires when the order carries a limit price but its trigger_price field is missing. The adapter cannot construct any Coinbase stop-limit configuration without the stop price, so it bails before the HTTP request.","triggerScenarios":"Submitting OrderType::StopLimit where the order's trigger_price is None; building the order with price set but trigger left unset; order factory invocation that omits the trigger_price/stop price argument.","commonSituations":"Confusing the adapter's trigger semantics with other venues that call it stop_price and forget to pass it; refactoring order construction and dropping the trigger parameter; copying a LIMIT order construction and adding only an order type change.","solutions":["Provide the trigger price when constructing the StopLimit order (factory trigger_price argument).","Double-check the order instance passed to the adapter has trigger_price set, not just price.","If no trigger is desired, the order is a plain LIMIT, not STOP_LIMIT — change the order type."],"exampleFix":"// before\nlet order = factory.stop_limit(instrument.id(), side, qty, limit_price, /* trigger missing */);\n// after\nlet order = factory.stop_limit(\n    instrument.id(),\n    side,\n    qty,\n    limit_price,\n    trigger_price, // required for STOP_LIMIT\n);","handlingStrategy":"validation","validationCode":"fn ensure_stop_limit_trigger(order: &OrderRequest) -> Result<(), String> {\n    if order.order_type == OrderType::StopLimit && order.trigger_price.is_none() {\n        return Err(format!(\"{}: STOP_LIMIT requires trigger_price\", order.client_order_id));\n    }\n    Ok(())\n}\nensure_stop_limit_trigger(&req)?;","typeGuard":"fn has_trigger(o: &OrderRequest) -> bool { matches!(o.order_type, OrderType::StopLimit) && o.trigger_price.is_some() }","tryCatchPattern":null,"preventionTips":["Pass trigger_price explicitly in every stop-limit factory call.","Centralize order construction so required fields per order type are enforced in one place.","Don't derive stop-limit orders by mutating LIMIT orders."],"tags":["order-submission","validation","missing-trigger-price"],"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"}