{"record":{"id":"b1e8e7adc39c2212","repo":"nautechsystems/nautilus_trader","slug":"binance-futures-goodtilldate-requires-whole-second","errorCode":null,"errorMessage":"Binance Futures goodTillDate requires whole-second precision","messagePattern":"Binance Futures goodTillDate requires whole-second precision","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/binance/src/futures/execution.rs","lineNumber":1188,"sourceCode":"    }\n\n    anyhow::ensure!(\n        matches!(\n            order_type,\n            OrderType::Limit | OrderType::StopLimit | OrderType::LimitIfTouched\n        ),\n        \"Binance Futures does not support GTD for order type {order_type:?}\"\n    );\n    anyhow::ensure!(!post_only, \"Binance Futures GTD cannot be post-only\");\n\n    anyhow::ensure!(\n        product_type == BinanceProductType::UsdM,\n        \"Binance {product_type:?} Futures does not support native GTD\"\n    );\n\n    let expire_time = expire_time.context(\"Binance Futures GTD requires an expire_time\")?;\n    let expire_ns = expire_time.as_u64();\n    anyhow::ensure!(\n        expire_ns.is_multiple_of(NANOSECONDS_IN_SECOND),\n        \"Binance Futures goodTillDate requires whole-second precision\"\n    );\n\n    let minimum_ns = ts_now\n        .as_u64()\n        .checked_add(BINANCE_GTD_MIN_LEAD_SECS * NANOSECONDS_IN_SECOND)\n        .context(\"Binance Futures GTD minimum timestamp overflow\")?;\n    anyhow::ensure!(\n        expire_ns > minimum_ns,\n        \"Binance Futures goodTillDate must be strictly greater than current time plus {BINANCE_GTD_MIN_LEAD_SECS} seconds\"\n    );\n\n    let good_till_date = expire_ns / NANOSECONDS_IN_MILLISECOND;\n    anyhow::ensure!(\n        good_till_date < BINANCE_GTD_MAX_MILLIS,\n        \"Binance Futures goodTillDate must be smaller than {BINANCE_GTD_MAX_MILLIS}\"\n    );","sourceCodeStart":1170,"sourceCodeEnd":1206,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/a4b06ed870971b5671d12754ea138a3ab99b1dec/crates/adapters/binance/src/futures/execution.rs#L1170-L1206","documentation":"Binance's goodTillDate is expressed in milliseconds with second granularity, so the client requires the order's expire_time (UnixNanos) to be a whole number of seconds — expire_ns must be a multiple of 1_000_000_000. Any sub-second component (nanoseconds remainder) makes the request unrepresentable and the lifetime resolution fails fast rather than silently truncating the expiry.","triggerScenarios":"Setting an expire_time derived from a sub-second-precise timestamp, e.g. now + 15*60*1e9 + 123ms of drift from a nanosecond clock, or a datetime parsed with millisecond/microsecond fractions.","commonSituations":"Expiries computed from UnixNanos::now() plus an offset without rounding; expiry datetimes from configs or external systems that carry fractional seconds.","solutions":["Round the expire_time down (or up, mind the minimum lead) to whole seconds before submitting","Build expiries as seconds-precision datetimes (e.g. UnixNanos from a second-aligned timestamp)","Check the remainder: expire_ns % 1_000_000_000 == 0"],"exampleFix":"// before\nlet expire = UnixNanos::now().checked_add(15 * 60 * 1_000_000_000)?; // may carry ns remainder\n\n// after\nconst NS_PER_SEC: u64 = 1_000_000_000;\nlet expire = UnixNanos::from((UnixNanos::now().as_u64() / NS_PER_SEC + 15 * 60) * NS_PER_SEC);","handlingStrategy":"validation","validationCode":"const NS_PER_SEC: u64 = 1_000_000_000;\nlet ns = expire_time.as_u64();\nanyhow::ensure!(ns.is_multiple_of(NS_PER_SEC), \"expire_time must be whole seconds\");\n// or normalize first: expire = (ns / NS_PER_SEC) * NS_PER_SEC;","typeGuard":"fn is_whole_second_expiry(ns: u64) -> bool {\n    ns.is_multiple_of(1_000_000_000)\n}","tryCatchPattern":null,"preventionTips":["Always construct expiries from second-aligned timestamps (e.g. datetime truncated to seconds)","Add an assertion helper for expiry invariants used by every strategy setting GTD"],"tags":["binance-futures","gtd","expire-time","precision","rust"],"backgroundTag":"good-till-date-validation","analyzedSha":"a4b06ed870971b5671d12754ea138a3ab99b1dec","analyzedAt":"2026-08-16T22:54:50.089Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}