nautechsystems/nautilus_trader · error

cannot modify Lighter order {}: venue order_id not yet known

Error message

cannot modify Lighter order {}: venue order_id not yet known (await OrderAccepted before issuing modify)

What it means

Lighter identifies live orders by venue-assigned order_id, not by client_order_id. A modify request needs that venue id, which is only known after the submit has been acknowledged (OrderAccepted event). The adapter refuses the modify instead of sending a request Lighter could not match.

Source

Thrown at crates/adapters/lighter/src/execution.rs:1930

        &self,
        cmd: &ModifyOrder,
        credential: &Credential,
    ) -> anyhow::Result<PreparedModifyOrder> {
        let market_index = self
            .registry
            .market_index(&cmd.instrument_id)
            .ok_or_else(|| {
                anyhow::anyhow!(
                    "no Lighter market_index registered for instrument {}",
                    cmd.instrument_id,
                )
            })?;

        let voi = cmd
            .venue_order_id
            .or_else(|| self.dispatch.lookup_venue_order_id(&cmd.client_order_id))
            .ok_or_else(|| {
                anyhow::anyhow!(
                    "cannot modify Lighter order {}: venue order_id not yet known \
                     (await OrderAccepted before issuing modify)",
                    cmd.client_order_id,
                )
            })?;

        let venue_index: i64 = voi
            .as_str()
            .parse()
            .with_context(|| format!("Lighter venue_order_id `{voi}` is not an integer index"))?;

        let order = self.core.cache().try_order_owned(&cmd.client_order_id)?;
        let instrument = self
            .core
            .cache()
            .try_instrument(&cmd.instrument_id)?
            .clone();

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Wait for the OrderAccepted event for the client_order_id before issuing the modify.
  2. Check whether the original submit failed or is stuck; cancel/re-submit instead of modifying.
  3. If the strategy must adjust quotes fast, treat the pre-ack window as a no-op and re-issue the modify once the venue order id is cached (verify with dispatch.lookup_venue_order_id).

Example fix

// before
self.exec.modify_order(&modify_cmd).await?;
// after
if self.dispatch.lookup_venue_order_id(&modify_cmd.client_order_id).is_some() {
    self.exec.modify_order(&modify_cmd).await?;
} else {
    // defer until OrderAccepted arrives
}
Defensive patterns

Strategy: try-catch

Validate before calling

fn can_modify(dispatch: &Dispatch, cmd: &ModifyOrder) -> bool {
    cmd.venue_order_id.is_some()
        || dispatch.lookup_venue_order_id(&cmd.client_order_id).is_some()
}

Try / catch

match client.modify_order(&cmd).await {
    Err(e) if e.to_string().contains("venue order_id not yet known") => defer_or_cancel(&cmd).await?,
    r => r?,
}

Prevention

When it happens

Trigger: Calling dispatch_signed_modify_order (or client.modify_order) with a ModifyOrder command whose venue_order_id is None and whose client_order_id is not yet in the dispatch's lookup map — i.e. the submit is still in flight or unacknowledged.

Common situations: Race after submitting: strategy fires the modify immediately after order.submit() before the websocket OrderAccepted arrives; rebasing/trailing-stop logic on tight timers; replaying a command batch where the submit never succeeded; connectivity drop so the ack never lands.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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