nautechsystems/nautilus_trader · error

cannot claim venue order ID {} for settlement order {client_

Error message

cannot claim venue order ID {} for settlement order {client_order_id}: {e}

What it means

NautilusTrader's option settlement plan executor claims the venue order ID for each settlement leg in the execution cache. This error means `cache.add_venue_order_id` returned an error, so the venue order ID could not be associated with the settlement order's client order ID (typically because the client order ID is unknown to the cache or the venue order ID is already claimed by another order).

Source

Thrown at crates/execution/src/matching_engine/settlement.rs:188

            self.dispatch_order_event(OrderEventAny::Filled(leg.fill));
        }

        Ok(())
    }

    fn option_register_settlement_plan(&self, plan: &OptionSettlementPlan) -> anyhow::Result<()> {
        for leg in &plan.legs {
            let client_order_id = leg.order.client_order_id();
            let mut cache = self.cache.borrow_mut();
            cache
                .add_order(leg.order.clone(), leg.fill.position_id, None, false)
                .map_err(|e| {
                    anyhow::anyhow!("cannot add settlement order {client_order_id}: {e}")
                })?;
            cache
                .add_venue_order_id(&client_order_id, &leg.fill.venue_order_id, false)
                .map_err(|e| {
                    anyhow::anyhow!(
                        "cannot claim venue order ID {} for settlement order {client_order_id}: {e}",
                        leg.fill.venue_order_id
                    )
                })?;
        }
        Ok(())
    }

    fn option_should_exercise(&self, underlying_price: Price) -> bool {
        let strike = match self.instrument.strike_price() {
            Some(p) => p.as_decimal(),
            None => return false,
        };
        let spot = underlying_price.as_decimal();
        match self.instrument.option_kind() {
            Some(OptionKind::Call) => spot > strike,
            Some(OptionKind::Put) => strike > spot,
            None => false,

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Ensure each settlement leg's client order ID exists in the cache before applying the plan (the settlement order must have been added first).
  2. Check for duplicate venue order IDs across legs or against previously settled orders; regenerate unique venue order IDs per fill.
  3. Log the underlying cache error `{e}` to identify whether it is a missing order or an ID conflict, and fix the registration sequence accordingly.

Example fix

// before: applying plan without registering the settlement order first
apply_settlement_plan(plan);
// after: register each leg's client order and venue order ID in order
for leg in &plan.legs {
    cache.add_order(...)?:
    cache.add_venue_order_id(&leg.client_order_id, &leg.fill.venue_order_id, false)?;
}
Defensive patterns

Strategy: try-catch

Validate before calling

if cache.client_order_id(&leg.fill.venue_order_id).is_some() {
    return Err(anyhow!("venue order ID {} already claimed", leg.fill.venue_order_id));
}

Try / catch

match cache.add_venue_order_id(&client_order_id, &leg.fill.venue_order_id, false) {
    Ok(_) => {},
    Err(e) => log::error!("settlement claim failed: {e}"),
}

Prevention

When it happens

Trigger: Calling `option_apply_settlement_plan` (via `option_register_settlement_plan`) when a leg's client_order_id is not registered in the cache, or when `leg.fill.venue_order_id` was already claimed by a different client order ID.

Common situations: Replaying or restarting a settlement flow with cached/duplicate venue order IDs; registering a settlement plan whose client order IDs were never added to the cache; concurrent settlement of the same expired option position from two processes.

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/dfbc0348897a2610. Report an issue: GitHub.