nautechsystems/nautilus_trader · error

'sl_limit_price' requires 'sl_order_type' to be 'Limit'

Error message

'sl_limit_price' requires 'sl_order_type' to be 'Limit'

What it means

Cross-field validation in parse_bybit_tp_sl_params: sl_limit_price is only meaningful when sl_order_type is Limit; supplying the limit price together with a different (market) SL order type is rejected.

Source

Thrown at crates/adapters/bybit/src/common/parse.rs:1884

    if result.stop_loss.is_none() && has_sl_fields {
        anyhow::bail!("SL override fields require 'stop_loss' to be set");
    }

    if result.tp_order_type == Some(BybitOrderType::Limit) && result.tp_limit_price.is_none() {
        anyhow::bail!("'tp_order_type' is 'Limit' but 'tp_limit_price' was not provided");
    }

    if result.sl_order_type == Some(BybitOrderType::Limit) && result.sl_limit_price.is_none() {
        anyhow::bail!("'sl_order_type' is 'Limit' but 'sl_limit_price' was not provided");
    }

    if result.tp_limit_price.is_some() && result.tp_order_type != Some(BybitOrderType::Limit) {
        anyhow::bail!("'tp_limit_price' requires 'tp_order_type' to be 'Limit'");
    }

    if result.sl_limit_price.is_some() && result.sl_order_type != Some(BybitOrderType::Limit) {
        anyhow::bail!("'sl_limit_price' requires 'sl_order_type' to be 'Limit'");
    }

    result.close_on_trigger = params.get_bool("close_on_trigger");

    if let Some(value) = params.get("order_iv") {
        match get_price_str(params, "order_iv") {
            Some(s) => result.order_iv = Some(s),
            None => {
                anyhow::bail!("invalid type for 'order_iv': {value}, expected string or number")
            }
        }
    }

    if let Some(value) = params.get("mmp") {
        match value.as_bool() {
            Some(b) => result.mmp = Some(b),
            None => anyhow::bail!("invalid type for 'mmp': {value}, expected bool"),
        }

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Set 'sl_order_type' to "Limit" together with 'sl_limit_price'
  2. Remove 'sl_limit_price' when using a Market stop-loss

Example fix

// before
params.set("sl_limit_price", "39500");
// after
params.set("sl_order_type", "Limit");
params.set("sl_limit_price", "39500");
Defensive patterns

Strategy: validation

Validate before calling

fn validate_sl_price(params: &Params) -> Result<(), String> {
    if params.get("sl_limit_price").is_some()
        && params.get_str("sl_order_type") != Some("Limit") {
        return Err("sl_limit_price requires sl_order_type = Limit".into());
    }
    Ok(())
}

Type guard

fn is_sl_price_without_limit(params: &Params) -> bool {
    params.get("sl_limit_price").is_some()
        && params.get_str("sl_order_type") != Some("Limit")
}

Try / catch

match parse_bybit_tp_sl_params(&params) {
    Ok(p) => submit(p),
    Err(e) if e.to_string().contains("'sl_limit_price' requires 'sl_order_type'") => {
        log::warn("SL price given without Limit type; set sl_order_type=Limit or drop the price");
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Setting 'sl_limit_price' while 'sl_order_type' is missing or not "Limit".

Common situations: Configuring SL limit prices for market stop-losses; params built conditionally where sl_order_type is set later or under a different key.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/a0d3ddddd3b7c7f4. Report an issue: GitHub.