nautechsystems/nautilus_trader · error · anyhow::Error

Binance {product_type:?} Futures does not support native GTD

Error message

Binance {product_type:?} Futures does not support native GTD

What it means

Only the USD-margined futures product (UsdM, /fapi) supports Binance's native goodTillDate; the coin-margined product (CoinM, /dapi) has no equivalent parameter, so the client refuses native GTD for CoinM. The guard fires when an order qualifies for native GTD (correct type, not post-only) but config.product_type is CoinM. The intended alternative is local expiry management via manage_gtd_expiry=false, which submits GTC and lets the strategy cancel at expiry.

Source

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

        log::warn!(
            "Binance Futures GTD submitted as GTC because use_gtd=false. Enable manage_gtd_expiry on the submitting strategy"
        );
        return Ok(FuturesOrderLifetime {
            time_in_force: TimeInForce::Gtc,
            good_till_date: None,
        });
    }

    anyhow::ensure!(
        matches!(
            order_type,
            OrderType::Limit | OrderType::StopLimit | OrderType::LimitIfTouched
        ),
        "Binance Futures does not support GTD for order type {order_type:?}"
    );
    anyhow::ensure!(!post_only, "Binance Futures GTD cannot be post-only");

    anyhow::ensure!(
        product_type == BinanceProductType::UsdM,
        "Binance {product_type:?} Futures does not support native GTD"
    );

    let expire_time = expire_time.context("Binance Futures GTD requires an expire_time")?;
    let expire_ns = expire_time.as_u64();
    anyhow::ensure!(
        expire_ns.is_multiple_of(NANOSECONDS_IN_SECOND),
        "Binance Futures goodTillDate requires whole-second precision"
    );

    let minimum_ns = ts_now
        .as_u64()
        .checked_add(BINANCE_GTD_MIN_LEAD_SECS * NANOSECONDS_IN_SECOND)
        .context("Binance Futures GTD minimum timestamp overflow")?;
    anyhow::ensure!(
        expire_ns > minimum_ns,
        "Binance Futures goodTillDate must be strictly greater than current time plus {BINANCE_GTD_MIN_LEAD_SECS} seconds"

View on GitHub (pinned to a4b06ed870)

Solutions

  1. Use product_type UsdM if native GTD is required
  2. For CoinM, set manage_gtd_expiry=false on the submitting strategy so GTD submits as GTC and the strategy expires the order itself
  3. Or replace Gtd with Gtc plus strategy-side cancel-on-time logic

Example fix

// before: CoinM client + strategy with manage_gtd_expiry=true submits GTD order
let order = Order::limit(instrument_id, side, qty, price)
    .time_in_force(TimeInForce::Gtd).expire_time(expiry);

// after: keep CoinM but let the strategy manage expiry
// strategy config: manage_gtd_expiry = false  (order submits as GTC, strategy cancels at expiry)
// or switch the client to UsdM for native GTD
Defensive patterns

Strategy: validation

Validate before calling

use binance product enum;

if order.time_in_force() == TimeInForce::Gtd && strategy.manage_gtd_expiry {
    anyhow::ensure!(
        config.product_type == BinanceProductType::UsdM,
        "native GTD needs UsdM; for CoinM set manage_gtd_expiry=false"
    );
}

Type guard

fn product_supports_native_gtd(product_type: BinanceProductType) -> bool {
    product_type == BinanceProductType::UsdM
}

Prevention

When it happens

Trigger: Running BinanceFuturesExecutionClient with product_type: CoinM and submitting a GTD order from a strategy with manage_gtd_expiry enabled (Limit/StopLimit/LimitIfTouched, not post-only).

Common situations: Porting a USD-M strategy config to COIN-M venues (BTCUSDT_PERP vs BTCUSD_PERM style symbols) without adjusting TIF handling; enabling native GTD globally on a multi-product deployment.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@a4b06ed870 (2026-08-16). Data as JSON: /api/errors/40177774c09f1b05. Report an issue: GitHub.