{"record":{"id":"32b1e6ed8fa80729","repo":"nautechsystems/nautilus_trader","slug":"lighter-gtd-expire-time-must-be-no-more-than-30-da","errorCode":null,"errorMessage":"Lighter GTD expire_time must be no more than 30 days from now","messagePattern":"Lighter GTD expire_time must be no more than 30 days from now","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/lighter/src/websocket/dispatch.rs","lineNumber":2072,"sourceCode":"    tif: &TimeInForce,\n    expire_time: Option<UnixNanos>,\n    now_ms: i64,\n) -> anyhow::Result<i64> {\n    if order_type == OrderType::Market {\n        return Ok(ORDER_EXPIRY_IOC);\n    }\n\n    if matches!(tif, TimeInForce::Gtd)\n        && let Some(ts) = expire_time\n    {\n        let expiry_ms = (ts.as_u64() / 1_000_000) as i64;\n        let min_expiry_ms = now_ms.saturating_add(ORDER_EXPIRY_MIN_GTD_MS);\n        let max_expiry_ms = now_ms.saturating_add(ORDER_EXPIRY_MAX_GTD_MS);\n        anyhow::ensure!(\n            expiry_ms >= min_expiry_ms,\n            \"Lighter GTD expire_time must be at least 5 minutes from now (plus 1 second transport margin)\",\n        );\n        anyhow::ensure!(\n            expiry_ms <= max_expiry_ms,\n            \"Lighter GTD expire_time must be no more than 30 days from now\",\n        );\n        return Ok(expiry_ms);\n    }\n\n    if is_conditional_order(order_type) && matches!(tif, TimeInForce::Ioc) {\n        return Ok(now_ms.saturating_add(ORDER_EXPIRY_DEFAULT_GTC_MS));\n    }\n\n    if matches!(tif, TimeInForce::Ioc | TimeInForce::Fok) {\n        return Ok(ORDER_EXPIRY_IOC);\n    }\n\n    Ok(now_ms.saturating_add(ORDER_EXPIRY_DEFAULT_GTC_MS))\n}\n\nfn is_conditional_market_order(order_type: OrderType) -> bool {","sourceCodeStart":2054,"sourceCodeEnd":2090,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/lighter/src/websocket/dispatch.rs#L2054-L2090","documentation":"Lighter imposes venue-side limits on GTD (Good-Til-Date) order expiry timestamps. The adapter validates that expire_time is at least 5 minutes from now (plus a 1s transport margin) and at most 30 days out. This error fires when expiry_ms exceeds the 30-day maximum computed from current time.","triggerScenarios":"Submitting or modifying a GTD order whose expire_time is more than ORDER_EXPIRY_MAX_GTD_MS (30 days) in the future, e.g. a strategy passing a 60-day expiry or a hardcoded far-future timestamp.","commonSituations":"Configured order TTL longer than the venue permits; default strategy time_in_expiry values ported from another adapter (e.g. Binance allows longer); unit confusion (ms vs seconds) inflating the timestamp.","solutions":["Reduce the GTD expire_time to 30 days from now or less","If a longer horizon is needed, use a non-GTD time-in-force (e.g. GTC) or re-issue/extend the order periodically within 30 days","Check any expire-time configuration for ms-vs-s or other unit errors inflating the value"],"exampleFix":"// before\nlet expire_time = now_ms + 60 * 24 * 3600 * 1000; // 60 days\n// after\nlet expire_time = now_ms + 30 * 24 * 3600 * 1000; // 30 days (venue max)","handlingStrategy":"validation","validationCode":"let max_expiry = now_ms + ORDER_EXPIRY_MAX_GTD_MS;\nlet min_expiry = now_ms + ORDER_EXPIRY_MIN_GTD_MS;\nanyhow::ensure!(expiry_ms >= min_expiry && expiry_ms <= max_expiry, \"GTD expiry out of venue range\");","typeGuard":"fn is_valid_gtd_expiry(expiry_ms: i64, now_ms: i64) -> bool {\n    expiry_ms >= now_ms + ORDER_EXPIRY_MIN_GTD_MS && expiry_ms <= now_ms + ORDER_EXPIRY_MAX_GTD_MS\n}","tryCatchPattern":"match client.submit_order(order) {\n    Err(e) if e.to_string().contains(\"no more than 30 days\") => {\n        // clamp expiry to 30 days and resubmit\n    }\n    other => other?,\n}","preventionTips":["Clamp GTD expiry to now+30d at order construction time","Prefer GTC for long-horizon orders","Unit-test expiry computation for ms/second confusion"],"tags":["rust","order-submission","validation","gtd"],"backgroundTag":"value-out-of-range","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}