nautechsystems/nautilus_trader · error

invalid price for '{key}': '{s}', expected a finite non-nega

Error message

invalid price for '{key}': '{s}', expected a finite non-negative number

What it means

parse_bybit_tp_sl_params also accepts auxiliary override fields (trigger_by, order_type, limit_price, trigger_price for TP/SL) as numeric strings. Each is parsed as f64 and rejected with this error if the value is not finite (NaN/inf) or is negative.

Source

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

        result.stop_loss = Some(p);
    }

    for (key, setter) in [
        (
            "tp_limit_price",
            &mut result.tp_limit_price as &mut Option<String>,
        ),
        ("sl_limit_price", &mut result.sl_limit_price),
        ("tp_trigger_price", &mut result.tp_trigger_price),
        ("sl_trigger_price", &mut result.sl_trigger_price),
    ] {
        if let Some(s) = get_price_str(params, key) {
            let v: f64 = s
                .parse()
                .map_err(|_| anyhow::anyhow!("invalid price for '{key}': '{s}'"))?;

            if !v.is_finite() || v < 0.0 {
                anyhow::bail!(
                    "invalid price for '{key}': '{s}', expected a finite non-negative number"
                );
            }
            *setter = Some(s);
        }
    }

    if let Some(s) = params.get_str("tp_trigger_by") {
        result.tp_trigger_by = Some(parse_trigger_type(s)?);
    }

    if let Some(s) = params.get_str("sl_trigger_by") {
        result.sl_trigger_by = Some(parse_trigger_type(s)?);
    }

    if let Some(s) = params.get_str("tp_order_type") {
        result.tp_order_type = Some(parse_tp_sl_order_type(s)?);
    }

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Ensure the value is a finite non-negative number before putting it in params
  2. Fix upstream math producing NaN/Infinity (e.g. division by zero) or use a fallback value
  3. Validate/parse the numeric string in your strategy before order submission

Example fix

// before
let tp_trigger = indicator_value / zero_var; // may be NaN
params.insert("tp_trigger_price", tp_trigger.to_string());
// after
let tp_trigger = if indicator_value.is_finite() && indicator_value >= 0.0 { indicator_value } else { fallback };
params.insert("tp_trigger_price", tp_trigger.to_string());
Defensive patterns

Strategy: validation

Validate before calling

import math
v = float(params[key])
assert math.isfinite(v) and v >= 0, f"{key} must be a finite non-negative number, got {v}"

Type guard

fn is_finite_non_negative(s: &str) -> bool {
    s.parse::<f64>().map(|v| v.is_finite() && v >= 0.0).unwrap_or(false)
}

Try / catch

for key in ["tp_trigger_price", "tp_limit_price", "sl_trigger_price", "sl_limit_price"] {
    if let Some(s) = params.get(key) {
        assert!(is_finite_non_negative(s), "bad {key}: {s}");
    }
}

Prevention

When it happens

Trigger: Passing params like tp_trigger_price='NaN', tp_limit_price='Infinity', or a negative value such as sl_trigger_price='-0.1' in the TP/SL params map.

Common situations: Division by zero or NaN propagating from indicator math into trigger prices, JSON configs containing Infinity, or sign bugs in delta-based trigger computation.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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