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

  1. Use TimeInForce::Gtc, TimeInForce::Day, or TimeInForce::Gtd (with a positive expiry) for conditional market orders
  2. If IOC behavior is required, submit the order without the conditional wrapper or handle expiry at the strategy layer
  3. 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

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


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/48d7568c68681f22. Report an issue: GitHub.