nautechsystems/nautilus_trader · error · anyhow::Error

Binance Futures GTD cannot be post-only

Error message

Binance Futures GTD cannot be post-only

What it means

The Binance futures native GTD path rejects post-only orders: a goodTillDate expiry combined with post_only is not a supported combination on the venue, so the lifetime resolution fails before submission. The guard runs after the order-type check and before the product-type check in the same function, and like the others only applies when manage_gtd_expiry (use_gtd) is enabled on the submitting strategy.

Source

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

    if !use_gtd {
        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!(

View on GitHub (pinned to a4b06ed870)

Solutions

  1. Disable post_only on GTD orders
  2. Drop the expiry (use plain Gtc post-only) if maker-only behavior matters more than the expiry
  3. Or disable manage_gtd_expiry so GTD downgrades to GTC post-only instead of erroring

Example fix

// before
let order = Order::limit(instrument_id, side, qty, price)
    .time_in_force(TimeInForce::Gtd).expire_time(expiry).post_only(true);

// after
let order = Order::limit(instrument_id, side, qty, price)
    .time_in_force(TimeInForce::Gtd).expire_time(expiry).post_only(false);
Defensive patterns

Strategy: validation

Validate before calling

use nautilus_model::enums::TimeInForce;

if order.time_in_force() == TimeInForce::Gtd && strategy.manage_gtd_expiry {
    anyhow::ensure!(!order.post_only(), "GTD + post_only rejected by Binance Futures");
}

Type guard

fn gtd_post_only_ok(order: &OrderAny) -> bool {
    !(order.time_in_force() == TimeInForce::Gtd && order.post_only())
}

Prevention

When it happens

Trigger: Submitting a Limit order with TimeInForce::Gtd, an expire_time, and post_only=true from a strategy with manage_gtd_expiry enabled — e.g. a market-making strategy that defaulted post_only on all quoting orders while also setting expiries.

Common situations: Market-making configs that globally enable post_only; strategies combining expiry management with maker-only quoting for the first time.

Related errors


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