nautechsystems/nautilus_trader · error

Binance only supports TrailingOffsetType::BasisPoints…

Error message

Binance only supports TrailingOffsetType::BasisPoints, received {offset_type:?}

What it means

Binance USDT-M futures trailing-stop orders only support callback rates expressed in basis points. During order validation in `validate_order`, if the Nautilus order carries a `trailing_offset_type` other than `TrailingOffsetType::BasisPoints`, the adapter rejects the submission with `anyhow::ensure!`. The offset must also be convertible to a valid Binance callback rate via `trailing_offset_to_callback_rate`.

Solutions

  1. Change the order's trailing offset type to `TrailingOffsetType::BasisPoints` and express the offset in basis points (e.g. 50 bps = 0.5%).
  2. Build trailing-stop orders per venue instead of reusing one order definition across venues.
  3. Convert a price-based offset to basis points relative to the trigger/current price before submitting to Binance.
  4. Verify with `trailing_offset_to_callback_rate` semantics that the basis-point offset falls within Binance's allowed callback-rate range.

Example fix

// before
let order = OrderFactory::trailing_stop_market(...,
    TrailingOffset::Price(Price::from("100.0")),
    TrailingOffsetType::Price);
// after
let order = OrderFactory::trailing_stop_market(...,
    TrailingOffset::BasisPoints(50),
    TrailingOffsetType::BasisPoints);
Defensive patterns

Strategy: validation

Validate before calling

fn can_submit_trailing(order: &OrderAny) -> Result<(), String> {
    match order.trailing_offset_type() {
        Some(t) if t == TrailingOffsetType::BasisPoints => Ok(()),
        Some(t) => Err(format!("Binance needs BasisPoints trailing offset, got {t:?}")),
        None => Ok(()), // not a trailing order
    }
}

Type guard

fn is_binance_trailing(order: &OrderAny) -> bool {
    matches!(order.trailing_offset_type(), Some(TrailingOffsetType::BasisPoints) | None)
}

Try / catch

match client.submit_order(cmd).await {
    Err(e) if e.to_string().contains("TrailingOffsetType") => {
        // reconfigure order to BasisPoints and resubmit
    }
    other => other?,
}

Prevention

When it happens

Trigger: Submitting a `SubmitOrder` command for a trailing-stop/trailing-stop-market order to a BinanceFuturesExecutionClient where `order.trailing_offset_type()` is `Price`, `BasisPoints` is not set, or any variant other than `BasisPoints` (e.g. a trailing order built with a price-based offset for another venue and reused for Binance).

Common situations: Reusing a trailing-stop order definition written for a venue that supports price-based trailing offsets (e.g. Bybit/FTX-style absolute offsets) on Binance; routing a multi-venue strategy without per-venue offset configuration; mistakenly passing `trailing_offset_type=TrailingOffsetType::Price` with an absolute offset value.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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

Appendix: source

Thrown at crates/adapters/binance/src/futures/execution.rs:3640

                        }
                    }
                }
            }

            Ok(())
        });

        Ok(())
    }
}

fn validate_order(
    client: &BinanceFuturesExecutionClient,
    cmd: &SubmitOrder,
    order: &OrderAny,
) -> anyhow::Result<ValidatedOrder> {
    if let Some(offset_type) = order.trailing_offset_type() {
        anyhow::ensure!(
            offset_type == TrailingOffsetType::BasisPoints,
            "Binance only supports TrailingOffsetType::BasisPoints, received {offset_type:?}"
        );

        if let Some(offset) = order.trailing_offset() {
            trailing_offset_to_callback_rate(offset)?;
        }
    }

    let close_position = cmd
        .params
        .as_ref()
        .and_then(|params| params.get_bool(PARAMS_CLOSE_POSITION))
        .unwrap_or(false);

    if close_position {
        let order_type = order.order_type();
        anyhow::ensure!(

View on GitHub (pinned to 18893faf8b)