nautechsystems/nautilus_trader · error
Lighter conditional market orders require a positive expiry;
Error message
Lighter conditional market orders require a positive expiry; Nautilus IOC cannot be represented because the venue uses IOC for post-trigger execution
What it means
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.
Source
Thrown at crates/adapters/lighter/src/websocket/dispatch.rs:2006
if order_type == OrderType::Market {
return match tif {
TimeInForce::Gtc | TimeInForce::Ioc => Ok(LighterTimeInForce::ImmediateOrCancel),
TimeInForce::Fok => anyhow::bail!(
"Lighter has no fill-or-kill TIF; reject FOK at the strategy or use IOC explicitly",
),
other => anyhow::bail!(
"Lighter market orders support only TimeInForce::Gtc or TimeInForce::Ioc, was TimeInForce::{other:?}",
),
};
}
if is_conditional_market_order(order_type) {
return match tif {
TimeInForce::Gtc | TimeInForce::Day | TimeInForce::Gtd => {
Ok(LighterTimeInForce::ImmediateOrCancel)
}
TimeInForce::Ioc => anyhow::bail!(
"Lighter conditional market orders require a positive expiry; Nautilus IOC cannot be represented because the venue uses IOC for post-trigger execution",
),
TimeInForce::Fok => anyhow::bail!(
"Lighter has no fill-or-kill TIF; reject FOK at the strategy or use IOC explicitly",
),
other => anyhow::bail!(
"Lighter conditional market orders do not support TimeInForce::{other:?}",
),
};
}
match tif {
TimeInForce::Ioc => Ok(LighterTimeInForce::ImmediateOrCancel),
TimeInForce::Fok => anyhow::bail!(
"Lighter has no fill-or-kill TIF; reject FOK at the strategy or use IOC explicitly",
),
TimeInForce::Gtc | TimeInForce::Day | TimeInForce::Gtd => {
Ok(LighterTimeInForce::GoodTillTime)View on GitHub (pinned to 18893faf8b)
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
Example fix
// before order_factory.stop_market(..., tif=TimeInForce.IOC) // after order_factory.stop_market(..., tif=TimeInForce.GTD, expire_time=expiry)
Defensive patterns
Strategy: validation
Validate before calling
// Rust
fn valid_conditional_market_tif(tif: TimeInForce) -> bool {
matches!(tif, TimeInForce::Gtc | TimeInForce::Day | TimeInForce::Gtd)
}
assert!(valid_conditional_market_tif(order.tif()), "use GTC/Day/GTD with positive expiry for Lighter conditional market orders"); Type guard
fn is_conditional_market_tif_supported(tif: TimeInForce) -> bool {
matches!(tif, TimeInForce::Gtc | TimeInForce::Day | TimeInForce::Gtd)
} Try / catch
// Rust
match submit_algo_order(order) {
Err(e) if e.to_string().contains("conditional market orders") => {
warn!("TIF {tif:?} unsupported for Lighter conditional orders; retrying as GTD");
}
other => other?,
} Prevention
- 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
When it happens
Trigger: Submitting a conditional market order (e.g. trigger-market / stop-market routed through the conditional path) with TimeInForce::Ioc on the Lighter adapter.
Common situations: 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.
Related errors
- Lighter conditional market orders do not support TimeInForce
- Lighter market orders support only TimeInForce::Gtc or TimeI
- Lighter does not support TimeInForce::{other:?}
- Unsupported `TimeInForce` for Binance: {value:?}
- Binance Spot does not support native GTD; set use_gtd=false
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/48d7568c68681f22.
Report an issue: GitHub.