nautechsystems/nautilus_trader · error

'tp_order_type' is 'Limit' but 'tp_limit_price' was not prov

Error message

'tp_order_type' is 'Limit' but 'tp_limit_price' was not provided

What it means

When 'tp_order_type' is Limit, Bybit requires a limit price for the take-profit order. The parser enforces this locally and bails if 'tp_limit_price' is missing so the request does not fail at the exchange.

Source

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

        || result.tp_order_type.is_some()
        || result.tp_limit_price.is_some()
        || result.tp_trigger_price.is_some();

    let has_sl_fields = result.sl_trigger_by.is_some()
        || result.sl_order_type.is_some()
        || result.sl_limit_price.is_some()
        || result.sl_trigger_price.is_some();

    if result.take_profit.is_none() && has_tp_fields {
        anyhow::bail!("TP override fields require 'take_profit' to be set");
    }

    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") {

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Add a 'tp_limit_price' value when 'tp_order_type' is Limit
  2. Change 'tp_order_type' to "Market" if a limit price is not intended

Example fix

// before
params.set("tp_order_type", "Limit");
// after
params.set("tp_order_type", "Limit");
params.set("tp_limit_price", "45000");
Defensive patterns

Strategy: validation

Validate before calling

fn validate_tp_limit(params: &Params) -> Result<(), String> {
    if params.get_str("tp_order_type") == Some("Limit") && params.get("tp_limit_price").is_none() {
        return Err("tp_order_type Limit requires tp_limit_price".into());
    }
    Ok(())
}

Type guard

fn is_limit_tp_missing_price(params: &Params) -> bool {
    params.get_str("tp_order_type") == Some("Limit")
        && params.get("tp_limit_price").is_none()
}

Try / catch

match parse_bybit_tp_sl_params(&params) {
    Ok(p) => submit(p),
    Err(e) if e.to_string().contains("'tp_limit_price' was not provided") => {
        log::warn("Limit TP without price; add tp_limit_price or switch to Market");
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Setting params 'tp_order_type' = "Limit" without providing 'tp_limit_price'.

Common situations: Copying TP/SL params that specify a limit order type but relying on defaults that only set the trigger price; switching order type from Market to Limit without adding a price.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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