{"record":{"id":"48d7568c68681f22","repo":"nautechsystems/nautilus_trader","slug":"lighter-conditional-market-orders-require-a-positi","errorCode":null,"errorMessage":"Lighter conditional market orders require a positive expiry; Nautilus IOC cannot be represented because the venue uses IOC for post-trigger execution","messagePattern":"Lighter conditional market orders require a positive expiry; Nautilus IOC cannot be represented because the venue uses IOC for post-trigger execution","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/lighter/src/websocket/dispatch.rs","lineNumber":2006,"sourceCode":"\n    if order_type == OrderType::Market {\n        return match tif {\n            TimeInForce::Gtc | TimeInForce::Ioc => Ok(LighterTimeInForce::ImmediateOrCancel),\n            TimeInForce::Fok => anyhow::bail!(\n                \"Lighter has no fill-or-kill TIF; reject FOK at the strategy or use IOC explicitly\",\n            ),\n            other => anyhow::bail!(\n                \"Lighter market orders support only TimeInForce::Gtc or TimeInForce::Ioc, was TimeInForce::{other:?}\",\n            ),\n        };\n    }\n\n    if is_conditional_market_order(order_type) {\n        return match tif {\n            TimeInForce::Gtc | TimeInForce::Day | TimeInForce::Gtd => {\n                Ok(LighterTimeInForce::ImmediateOrCancel)\n            }\n            TimeInForce::Ioc => anyhow::bail!(\n                \"Lighter conditional market orders require a positive expiry; Nautilus IOC cannot be represented because the venue uses IOC for post-trigger execution\",\n            ),\n            TimeInForce::Fok => anyhow::bail!(\n                \"Lighter has no fill-or-kill TIF; reject FOK at the strategy or use IOC explicitly\",\n            ),\n            other => anyhow::bail!(\n                \"Lighter conditional market orders do not support TimeInForce::{other:?}\",\n            ),\n        };\n    }\n\n    match tif {\n        TimeInForce::Ioc => Ok(LighterTimeInForce::ImmediateOrCancel),\n        TimeInForce::Fok => anyhow::bail!(\n            \"Lighter has no fill-or-kill TIF; reject FOK at the strategy or use IOC explicitly\",\n        ),\n        TimeInForce::Gtc | TimeInForce::Day | TimeInForce::Gtd => {\n            Ok(LighterTimeInForce::GoodTillTime)","sourceCodeStart":1988,"sourceCodeEnd":2024,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/lighter/src/websocket/dispatch.rs#L1988-L2024","documentation":"Lighter conditional (triggered) market orders require a positive expiry timestamp, and the venue reuses IOC semantics for post-trigger execution. Nautilus TimeInForce::Ioc therefore cannot be mapped onto a conditional market order, so the adapter rejects it explicitly instead of producing a subtly wrong venue order.","triggerScenarios":"Submitting a conditional market order (e.g. trigger-market / stop-market routed through the conditional path) with TimeInForce::Ioc on the Lighter adapter.","commonSituations":"Copy-pasting IOC from plain market-order code into conditional order creation; assuming IOC means 'cancel if not triggered' when on Lighter it governs post-trigger execution.","solutions":["Use TimeInForce::Gtc, TimeInForce::Day, or TimeInForce::Gtd (with a positive expiry) for conditional market orders","If IOC behavior is required, submit the order without the conditional wrapper or handle expiry at the strategy layer","Validate TIF against order type in a pre-submit hook"],"exampleFix":"// before\norder_factory.stop_market(..., tif=TimeInForce.IOC)\n// after\norder_factory.stop_market(..., tif=TimeInForce.GTD, expire_time=expiry)","handlingStrategy":"validation","validationCode":"// Rust\nfn valid_conditional_market_tif(tif: TimeInForce) -> bool {\n    matches!(tif, TimeInForce::Gtc | TimeInForce::Day | TimeInForce::Gtd)\n}\nassert!(valid_conditional_market_tif(order.tif()), \"use GTC/Day/GTD with positive expiry for Lighter conditional market orders\");","typeGuard":"fn is_conditional_market_tif_supported(tif: TimeInForce) -> bool {\n    matches!(tif, TimeInForce::Gtc | TimeInForce::Day | TimeInForce::Gtd)\n}","tryCatchPattern":"// Rust\nmatch submit_algo_order(order) {\n    Err(e) if e.to_string().contains(\"conditional market orders\") => {\n        warn!(\"TIF {tif:?} unsupported for Lighter conditional orders; retrying as GTD\");\n    }\n    other => other?,\n}","preventionTips":["Never reuse plain-market-order IOC settings for conditional orders","Always set a positive expiry for conditional orders","Unit-test TIF mapping for every conditional order type"],"tags":["rust","conditional-orders","time-in-force","exchange-adapter"],"backgroundTag":"unsupported-enum-value","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"}