nautechsystems/nautilus_trader · error · anyhow::Error

Binance Spot does not support native GTD; set use_gtd=false

Error message

Binance Spot does not support native GTD; set use_gtd=false and enable manage_gtd_expiry on the submitting strategy

What it means

Binance Spot has no native GTD (good-til-date) time in force. When the execution client is configured with use_gtd=true (the default), submitting a TimeInForce::Gtd order bails here with a pointer to the two supported alternatives; with use_gtd=false, GTD is instead downgraded to GTC with a warning and the strategy is expected to cancel the order itself at expiry via manage_gtd_expiry.

Source

Thrown at crates/adapters/binance/src/spot/enums.rs:141

///
/// # Errors
///
/// Returns an error if the time in force is not supported on Binance Spot.
pub fn time_in_force_to_binance_spot(
    tif: TimeInForce,
    use_gtd: bool,
) -> anyhow::Result<BinanceTimeInForce> {
    match tif {
        TimeInForce::Gtc => Ok(BinanceTimeInForce::Gtc),
        TimeInForce::Ioc => Ok(BinanceTimeInForce::Ioc),
        TimeInForce::Fok => Ok(BinanceTimeInForce::Fok),
        TimeInForce::Gtd if !use_gtd => {
            log::warn!(
                "Binance Spot does not support GTD; submitting as GTC because use_gtd=false. Enable manage_gtd_expiry on the submitting strategy"
            );
            Ok(BinanceTimeInForce::Gtc)
        }
        TimeInForce::Gtd => anyhow::bail!(
            "Binance Spot does not support native GTD; set use_gtd=false and enable manage_gtd_expiry on the submitting strategy"
        ),
        _ => anyhow::bail!("Unsupported time in force for Binance Spot: {tif:?}"),
    }
}

#[cfg(test)]
mod tests {
    use rstest::rstest;

    use super::*;

    #[rstest]
    #[case(OrderType::Market, false, BinanceSpotOrderType::Market)]
    #[case(OrderType::Limit, false, BinanceSpotOrderType::Limit)]
    #[case(OrderType::Limit, true, BinanceSpotOrderType::LimitMaker)]
    #[case(OrderType::StopMarket, false, BinanceSpotOrderType::StopLoss)]
    #[case(OrderType::StopLimit, false, BinanceSpotOrderType::StopLossLimit)]

View on GitHub (pinned to a4b06ed870)

Solutions

  1. Set use_gtd=false in the Binance execution client config and enable manage_gtd_expiry on the submitting strategy so expiry is handled locally
  2. Or change the order to GTC/IOC/FOK and manage cancellation yourself
  3. Keep use_gtd=true only as a fail-fast lint when you want GTD usage to be an error

Example fix

# before: default config (use_gtd=True) + GTD order -> error
config = BinanceExecClientConfig()

# after: downgrade GTD to GTC, strategy cancels at expiry
config = BinanceExecClientConfig(use_gtd=False)
strategy_config = MyStrategyConfig(manage_gtd_expiry=True)
Defensive patterns

Strategy: validation

Validate before calling

// before building the order
let use_gtd = exec_config.use_gtd;
if order_spec.time_in_force == TimeInForce::Gtd && use_gtd {
    // either flip the config or downgrade the order
    return Err(anyhow::anyhow!(
        "GTD requires use_gtd=false + manage_gtd_expiry, or use GTC"
    ));
}

Type guard

fn spot_tif_needs_downgrade(tif: TimeInForce, use_gtd: bool) -> bool {
    tif == TimeInForce::Gtd && !use_gtd
}

Prevention

When it happens

Trigger: Submitting an order with TimeInForce::Gtd while BinanceExecClientConfig.use_gtd == true. submit_order at spot/execution.rs:1505 calls this conversion explicitly to fail fast before any venue dispatch.

Common situations: Running with default adapter config and reusing expiry-aware orders from another venue; enabling use_gtd to deliberately catch GTD usage; porting futures strategies where GTD handling differed.

Related errors


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