{"record":{"id":"bba724d60f141cad","repo":"nautechsystems/nautilus_trader","slug":"conditional-order-missing-tpsl-indicator","errorCode":null,"errorMessage":"Conditional order missing tpsl indicator","messagePattern":"Conditional order missing tpsl indicator","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/hyperliquid/src/common/parse.rs","lineNumber":894,"sourceCode":"    }\n}\n\n/// Validates conditional order parameters from WebSocket data.\n///\n/// # Returns\n///\n/// `Ok(())` if parameters are valid, `Err` with description otherwise.\npub fn validate_conditional_order_params(\n    trigger_px: Option<&str>,\n    tpsl: Option<&HyperliquidTpSl>,\n    is_market: Option<bool>,\n) -> anyhow::Result<()> {\n    if trigger_px.is_none() {\n        anyhow::bail!(\"Conditional order missing trigger price\");\n    }\n\n    if tpsl.is_none() {\n        anyhow::bail!(\"Conditional order missing tpsl indicator\");\n    }\n\n    // No need to validate tpsl value - the enum type guarantees it's either Tp or Sl\n\n    if is_market.is_none() {\n        anyhow::bail!(\"Conditional order missing is_market flag\");\n    }\n\n    Ok(())\n}\n\n/// Parses trigger price from string to Decimal.\n///\n/// # Returns\n///\n/// Parsed Decimal value or error.\npub fn parse_trigger_price(trigger_px: &str) -> anyhow::Result<Decimal> {\n    Decimal::from_str_exact(trigger_px)","sourceCodeStart":876,"sourceCodeEnd":912,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/hyperliquid/src/common/parse.rs#L876-L912","documentation":"validate_conditional_order_params requires a tpsl indicator because Hyperliquid trigger orders must declare whether they are a take-profit (Tp) or stop-loss (Sl). A None tpsl cannot be encoded into the request, so the validator rejects it. The enum type guarantees a valid value; only presence is checked.","triggerScenarios":"Calling validate_conditional_order_params with tpsl: None — e.g. building a trigger order request where the TpSl discriminator was not set from user config or parsed params.","commonSituations":"Configuring stop-loss/take-profit orders where only the trigger price was supplied; generic order-building code reused for both plain trigger and TPSL orders, omitting the tpsl field for the latter.","solutions":["Set the tpsl field to HyperliquidTpSl::Tp or HyperliquidTpSl::Sl depending on the order's intent.","Derive tpsl automatically from order side and trigger direction before validation.","If no TP/SL semantics are intended, use the non-TPSL trigger order construction path that doesn't call this validator."],"exampleFix":"// before\nvalidate_conditional_order_params(Some(trigger_px), None, Some(false))?;\n// after\nvalidate_conditional_order_params(Some(trigger_px), Some(&HyperliquidTpSl::Sl), Some(false))?;","handlingStrategy":"validation","validationCode":"let tpsl = tpsl.or(if is_take_profit { Some(HyperliquidTpSl::Tp) } else { Some(HyperliquidTpSl::Sl) });\nvalidate_conditional_order_params(trigger_px, Some(&tpsl), is_market)?;","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always set the Tp/Sl discriminator when building TPSL orders.","Derive tpsl from order intent instead of threading Option through code.","Add unit tests covering both Tp and Sl conditional orders."],"tags":["conditional-order","missing-parameter","hyperliquid","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"}