nautechsystems/nautilus_trader · error

invalid type for 'mmp': {value}, expected bool

Error message

invalid type for 'mmp': {value}, expected bool

What it means

Type validation in parse_bybit_tp_sl_params: the 'mmp' order param exists but its value is not a JSON bool. Bybit requires mmp (market-maker protection) to be a boolean flag, so the raw value is rejected.

Source

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

    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"),
        }
    }

    if let Some(value) = params.get("smp_type") {
        let smp_type = value.as_str().ok_or_else(|| {
            anyhow::anyhow!("invalid type for 'smp_type': {value}, expected string")
        })?;
        result.smp_type = Some(parse_smp_type(smp_type)?);
    }

    if let Some(value) = params.get("position_idx") {
        let idx = value.as_i64().ok_or_else(|| {
            anyhow::anyhow!("invalid type for 'position_idx': {value}, expected integer")
        })?;
        result.position_idx = Some(match idx {
            0 => BybitPositionIdx::OneWay,
            1 => BybitPositionIdx::BuyHedge,
            2 => BybitPositionIdx::SellHedge,

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Pass 'mmp' as an actual boolean (true/false), not a string or number
  2. Coerce the source value with a bool parse before setting it in params

Example fix

// before
params.set("mmp", "true");
// after
params.set("mmp", true);
Defensive patterns

Strategy: type-guard

Validate before calling

fn validate_mmp(params: &Params) -> Result<(), String> {
    if let Some(v) = params.get("mmp") {
        if !v.is_bool() {
            return Err(format!("mmp must be bool, got {v}"));
        }
    }
    Ok(())
}

Type guard

fn as_bool(v: &Value) -> Option<bool> {
    v.as_bool()
}

Try / catch

match parse_bybit_tp_sl_params(&params) {
    Ok(p) => submit(p),
    Err(e) if e.to_string().contains("invalid type for 'mmp'") => {
        log::warn("mmp must be a JSON bool, not a string or number");
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Passing 'mmp' as the string "true"/"false", a number 0/1, or any other non-bool type in params.

Common situations: Environment/config-driven flags read as strings; JSON payloads where mmp was serialized as "true" instead of true.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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