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
- Wait for the OrderAccepted event for the client_order_id before issuing the modify.
- Check whether the original submit failed or is stuck; cancel/re-submit instead of modifying.
- 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
- Gate modifies on the OrderAccepted event, never on submit() returning.
- Maintain a pending-modify queue keyed by client_order_id drained on OrderAccepted.
- Log submit->ack latency to size the ack window in your strategy.
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
- IncompleteOrderReports { reports, detail: detail.into() }
- Unsupported order type {} for update_order
- WS modify order failed: {e}
- Modify order failed: {e}
- Invalid venue order ID: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/df5d85a37a0a64b2.
Report an issue: GitHub.